Chromium Code Reviews| 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 LOG(ERROR) << "Failed to parse SessionDescription."; | |
|
Ronghua Wu (Left Chromium)
2012/08/15 00:57:32
Can you just LOG the |reason|, so that you don't n
perkj_chrome
2012/08/15 09:12:30
Done.
| |
| 219 WebKit::WebString reason("Failed to parse SessionDescription."); | |
| 220 request.requestFailed(reason); | |
| 221 return; | |
| 222 } | |
| 223 talk_base::scoped_refptr<SetSessionDescriptionRequest> set_request( | |
| 224 new talk_base::RefCountedObject<SetSessionDescriptionRequest>(request)); | |
| 225 native_peer_connection_->SetLocalDescription(set_request.get(), native_desc); | |
| 226 } | |
| 227 | |
| 228 void RTCPeerConnectionHandler::setRemoteDescription( | |
| 229 const WebKit::WebRTCVoidRequest& request, | |
| 230 const WebKit::WebRTCSessionDescriptionDescriptor& description) { | |
| 231 webrtc::SessionDescriptionInterface* native_desc = | |
| 232 CreateNativeSessionDescription(description); | |
| 233 if (!native_desc) { | |
| 234 LOG(ERROR) << "Failed to parse SessionDescription."; | |
| 235 WebKit::WebString reason("Failed to parse SessionDescription."); | |
| 236 request.requestFailed(reason); | |
| 237 return; | |
| 238 } | |
| 239 talk_base::scoped_refptr<SetSessionDescriptionRequest> set_request( | |
| 240 new talk_base::RefCountedObject<SetSessionDescriptionRequest>(request)); | |
| 241 native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc); | |
| 242 } | |
| 243 | |
| 244 WebKit::WebRTCSessionDescriptionDescriptor | |
| 245 RTCPeerConnectionHandler::localDescription() { | |
| 246 const webrtc::SessionDescriptionInterface* native_desc = | |
| 247 native_peer_connection_->local_description(); | |
| 248 WebKit::WebRTCSessionDescriptionDescriptor description = | |
| 249 CreateWebKitSessionDescription(native_desc); | |
| 250 return description; | |
| 251 } | |
| 252 | |
| 253 WebKit::WebRTCSessionDescriptionDescriptor | |
| 254 RTCPeerConnectionHandler::remoteDescription() { | |
| 255 const webrtc::SessionDescriptionInterface* native_desc = | |
| 256 native_peer_connection_->remote_description(); | |
| 257 WebKit::WebRTCSessionDescriptionDescriptor description = | |
| 258 CreateWebKitSessionDescription(native_desc); | |
| 259 return description; | |
| 260 } | |
| 261 | |
| 262 bool RTCPeerConnectionHandler::updateICE( | |
| 263 const WebKit::WebRTCConfiguration& server_configuration, | |
| 264 const WebKit::WebMediaConstraints& options) { | |
| 265 webrtc::JsepInterface::IceServers servers; | |
| 266 GetNativeIceServers(server_configuration, &servers); | |
| 267 RTCMediaConstraints constraints(options); | |
| 268 return native_peer_connection_->UpdateIce(servers, | |
| 269 &constraints); | |
| 270 } | |
| 271 | |
| 272 bool RTCPeerConnectionHandler::addICECandidate( | |
| 273 const WebKit::WebRTCICECandidateDescriptor& candidate) { | |
| 274 scoped_ptr<webrtc::IceCandidateInterface> native_candidate( | |
| 275 dependency_factory_->CreateIceCandidate( | |
| 276 UTF16ToUTF8(candidate.sdpMid()), | |
| 277 candidate.sdpMLineIndex(), | |
| 278 UTF16ToUTF8(candidate.candidate()))); | |
| 279 if (!native_candidate.get()) { | |
| 280 LOG(ERROR) << "Could not create native ICE candidate."; | |
| 281 return false; | |
| 282 } | |
| 283 | |
| 284 bool return_value = | |
| 285 native_peer_connection_->AddIceCandidate(native_candidate.get()); | |
| 286 if (!return_value) | |
| 287 LOG(ERROR) << "Error processing ICE candidate."; | |
| 288 return return_value; | |
| 289 } | |
| 290 | |
| 291 bool RTCPeerConnectionHandler::addStream( | |
| 292 const WebKit::WebMediaStreamDescriptor& stream, | |
| 293 const WebKit::WebMediaConstraints& options) { | |
| 294 RTCMediaConstraints constraints(options); | |
| 295 return AddStream(stream, &constraints); | |
| 296 } | |
| 297 | |
| 298 void RTCPeerConnectionHandler::removeStream( | |
| 299 const WebKit::WebMediaStreamDescriptor& stream) { | |
| 300 RemoveStream(stream); | |
| 301 } | |
| 302 | |
| 303 void RTCPeerConnectionHandler::stop() { | |
| 304 DVLOG(1) << "RTCPeerConnectionHandler::stop"; | |
| 305 native_peer_connection_ = NULL; | |
| 306 } | |
| 307 | |
| 308 void RTCPeerConnectionHandler::OnError() { | |
| 309 // TODO(perkj): Implement. | |
| 310 NOTIMPLEMENTED(); | |
| 311 } | |
| 312 | |
| 313 void RTCPeerConnectionHandler::OnStateChange(StateType state_changed) { | |
| 314 switch (state_changed) { | |
| 315 case kReadyState: { | |
| 316 WebKit::WebRTCPeerConnectionHandlerClient::ReadyState ready_state = | |
| 317 GetWebKitReadyState(native_peer_connection_->ready_state()); | |
| 318 client_->didChangeReadyState(ready_state); | |
| 319 break; | |
| 320 } | |
| 321 case kIceState: { | |
| 322 WebKit::WebRTCPeerConnectionHandlerClient::ICEState ice_state = | |
| 323 GetWebKitIceState(native_peer_connection_->ice_state()); | |
| 324 client_->didChangeICEState(ice_state); | |
| 325 break; | |
| 326 } | |
| 327 default: | |
| 328 NOTREACHED(); | |
| 329 break; | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 void RTCPeerConnectionHandler::OnAddStream( | |
| 334 webrtc::MediaStreamInterface* stream) { | |
| 335 if (!stream) { | |
| 336 LOG(ERROR) << "OnAddStream: stream is null"; | |
| 337 return; | |
| 338 } | |
| 339 | |
| 340 DCHECK(remote_streams_.find(stream) == remote_streams_.end()); | |
| 341 WebKit::WebMediaStreamDescriptor descriptor = | |
| 342 CreateWebKitStreamDescriptor(stream); | |
| 343 remote_streams_.insert( | |
| 344 std::pair<webrtc::MediaStreamInterface*, | |
| 345 WebKit::WebMediaStreamDescriptor>(stream, descriptor)); | |
| 346 client_->didAddRemoteStream(descriptor); | |
| 347 } | |
| 348 | |
| 349 void RTCPeerConnectionHandler::OnRemoveStream( | |
| 350 webrtc::MediaStreamInterface* stream) { | |
| 351 if (!stream) { | |
| 352 LOG(ERROR) << "OnRemoveStream: stream is null"; | |
| 353 return; | |
| 354 } | |
| 355 | |
| 356 RemoteStreamMap::iterator it = remote_streams_.find(stream); | |
| 357 if (it == remote_streams_.end()) { | |
| 358 NOTREACHED() << "Stream not found"; | |
| 359 return; | |
| 360 } | |
| 361 WebKit::WebMediaStreamDescriptor descriptor = it->second; | |
| 362 DCHECK(!descriptor.isNull()); | |
| 363 remote_streams_.erase(it); | |
| 364 client_->didRemoveRemoteStream(descriptor); | |
| 365 } | |
| 366 | |
| 367 void RTCPeerConnectionHandler::OnIceCandidate( | |
| 368 const webrtc::IceCandidateInterface* candidate) { | |
| 369 std::string sdp; | |
| 370 if (!candidate->ToString(&sdp)) { | |
| 371 LOG(ERROR) << "OnIceCandidate: Could not get SDP string."; | |
| 372 return; | |
| 373 } | |
| 374 WebKit::WebRTCICECandidateDescriptor web_candidate; | |
| 375 web_candidate.initialize(UTF8ToUTF16(sdp), | |
| 376 UTF8ToUTF16(candidate->sdp_mid()), | |
| 377 candidate->sdp_mline_index()); | |
| 378 client_->didGenerateICECandidate(web_candidate); | |
| 379 } | |
| 380 | |
| 381 void RTCPeerConnectionHandler::OnIceComplete() { | |
| 382 // Generates a NULL ice candidate object. | |
| 383 WebKit::WebRTCICECandidateDescriptor web_candidate; | |
| 384 client_->didGenerateICECandidate(web_candidate); | |
| 385 } | |
| 386 | |
| 387 void RTCPeerConnectionHandler::OnRenegotiationNeeded() { | |
| 388 client_->doRenegotiate(); | |
| 389 } | |
| 390 | |
| 391 webrtc::SessionDescriptionInterface* | |
| 392 RTCPeerConnectionHandler::CreateNativeSessionDescription( | |
| 393 const WebKit::WebRTCSessionDescriptionDescriptor& description) { | |
| 394 std::string sdp = UTF16ToUTF8(description.sdp()); | |
| 395 std::string type = UTF16ToUTF8(description.type()); | |
| 396 webrtc::SessionDescriptionInterface* native_desc = | |
| 397 dependency_factory_->CreateSessionDescription(type, sdp); | |
| 398 if (!native_desc) { | |
| 399 LOG(ERROR) << "Failed to create native session description. Type: " | |
| 400 << type << " SDP: " << sdp; | |
| 401 return NULL; | |
| 402 } | |
| 403 | |
| 404 return native_desc; | |
| 405 } | |
| OLD | NEW |