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