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/peer_connection_handler_jsep.h" |
| 6 |
| 7 #include <utility> |
| 8 #include <vector> |
| 9 |
| 10 #include "base/bind.h" |
| 11 #include "base/logging.h" |
| 12 #include "base/string_number_conversions.h" |
| 13 #include "base/utf_string_conversions.h" |
| 14 #include "content/renderer/media/media_stream_dependency_factory.h" |
| 15 #include "content/renderer/media/media_stream_impl.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebICECandid
ateDescriptor.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebICEOption
s.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConne
ction00HandlerClient.h" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaHint
s.h" |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStre
amDescriptor.h" |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStre
amSource.h" |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSessionDe
scriptionDescriptor.h" |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" |
| 24 |
| 25 PeerConnectionHandlerJsep::PeerConnectionHandlerJsep( |
| 26 WebKit::WebPeerConnection00HandlerClient* client, |
| 27 MediaStreamImpl* msi, |
| 28 MediaStreamDependencyFactory* dependency_factory) |
| 29 : PeerConnectionHandlerBase(msi, dependency_factory), |
| 30 client_(client) { |
| 31 } |
| 32 |
| 33 PeerConnectionHandlerJsep::~PeerConnectionHandlerJsep() { |
| 34 } |
| 35 |
| 36 void PeerConnectionHandlerJsep::initialize( |
| 37 const WebKit::WebString& server_configuration, |
| 38 const WebKit::WebString& username) { |
| 39 native_peer_connection_ = dependency_factory_->CreatePeerConnection( |
| 40 UTF16ToUTF8(server_configuration), |
| 41 this); |
| 42 CHECK(native_peer_connection_); |
| 43 } |
| 44 |
| 45 WebKit::WebSessionDescriptionDescriptor PeerConnectionHandlerJsep::createOffer( |
| 46 const WebKit::WebMediaHints& hints) { |
| 47 WebKit::WebSessionDescriptionDescriptor offer; |
| 48 |
| 49 webrtc::MediaHints native_hints(hints.audio(), hints.video()); |
| 50 scoped_ptr<webrtc::SessionDescriptionInterface> native_offer( |
| 51 native_peer_connection_->CreateOffer(native_hints)); |
| 52 if (!native_offer.get()) { |
| 53 LOG(ERROR) << "Failed to create native offer"; |
| 54 return offer; |
| 55 } |
| 56 |
| 57 offer = CreateWebKitSessionDescription(native_offer.get()); |
| 58 return offer; |
| 59 } |
| 60 |
| 61 WebKit::WebSessionDescriptionDescriptor PeerConnectionHandlerJsep::createAnswer( |
| 62 const WebKit::WebString& offer, |
| 63 const WebKit::WebMediaHints& hints) { |
| 64 WebKit::WebSessionDescriptionDescriptor answer; |
| 65 |
| 66 webrtc::MediaHints native_hints(hints.audio(), hints.video()); |
| 67 scoped_ptr<webrtc::SessionDescriptionInterface> native_offer( |
| 68 dependency_factory_->CreateSessionDescription(UTF16ToUTF8(offer))); |
| 69 if (!native_offer.get()) { |
| 70 LOG(ERROR) << "Failed to create native offer"; |
| 71 return answer; |
| 72 } |
| 73 |
| 74 scoped_ptr<webrtc::SessionDescriptionInterface> native_answer( |
| 75 native_peer_connection_->CreateAnswer(native_hints, native_offer.get())); |
| 76 if (!native_answer.get()) { |
| 77 LOG(ERROR) << "Failed to create native answer"; |
| 78 return answer; |
| 79 } |
| 80 |
| 81 answer = CreateWebKitSessionDescription(native_answer.get()); |
| 82 return answer; |
| 83 } |
| 84 |
| 85 bool PeerConnectionHandlerJsep::setLocalDescription( |
| 86 Action action, |
| 87 const WebKit::WebSessionDescriptionDescriptor& description) { |
| 88 webrtc::PeerConnectionInterface::Action native_action; |
| 89 if (!GetNativeAction(action, &native_action)) |
| 90 return false; |
| 91 |
| 92 webrtc::SessionDescriptionInterface* native_desc = |
| 93 CreateNativeSessionDescription(description); |
| 94 if (!native_desc) |
| 95 return false; |
| 96 |
| 97 return native_peer_connection_->SetLocalDescription(native_action, |
| 98 native_desc); |
| 99 } |
| 100 |
| 101 bool PeerConnectionHandlerJsep::setRemoteDescription( |
| 102 Action action, |
| 103 const WebKit::WebSessionDescriptionDescriptor& description) { |
| 104 webrtc::PeerConnectionInterface::Action native_action; |
| 105 if (!GetNativeAction(action, &native_action)) |
| 106 return false; |
| 107 |
| 108 webrtc::SessionDescriptionInterface* native_desc = |
| 109 CreateNativeSessionDescription(description); |
| 110 if (!native_desc) |
| 111 return false; |
| 112 |
| 113 return native_peer_connection_->SetRemoteDescription(native_action, |
| 114 native_desc); |
| 115 } |
| 116 |
| 117 WebKit::WebSessionDescriptionDescriptor |
| 118 PeerConnectionHandlerJsep::localDescription() { |
| 119 const webrtc::SessionDescriptionInterface* native_desc = |
| 120 native_peer_connection_->local_description(); |
| 121 WebKit::WebSessionDescriptionDescriptor description = |
| 122 CreateWebKitSessionDescription(native_desc); |
| 123 return description; |
| 124 } |
| 125 |
| 126 WebKit::WebSessionDescriptionDescriptor |
| 127 PeerConnectionHandlerJsep::remoteDescription() { |
| 128 const webrtc::SessionDescriptionInterface* native_desc = |
| 129 native_peer_connection_->remote_description(); |
| 130 WebKit::WebSessionDescriptionDescriptor description = |
| 131 CreateWebKitSessionDescription(native_desc); |
| 132 return description; |
| 133 } |
| 134 |
| 135 bool PeerConnectionHandlerJsep::startIce(const WebKit::WebICEOptions& options) { |
| 136 webrtc::PeerConnectionInterface::IceOptions native_options; |
| 137 switch (options.candidateTypeToUse()) { |
| 138 case WebKit::WebICEOptions::CandidateTypeAll: |
| 139 native_options = webrtc::PeerConnectionInterface::kUseAll; |
| 140 break; |
| 141 case WebKit::WebICEOptions::CandidateTypeNoRelay: |
| 142 native_options = webrtc::PeerConnectionInterface::kNoRelay; |
| 143 break; |
| 144 case WebKit::WebICEOptions::CandidateTypeOnlyRelay: |
| 145 native_options = webrtc::PeerConnectionInterface::kOnlyRelay; |
| 146 break; |
| 147 default: |
| 148 NOTREACHED(); |
| 149 return false; |
| 150 } |
| 151 native_peer_connection_->StartIce(native_options); |
| 152 return true; |
| 153 } |
| 154 |
| 155 bool PeerConnectionHandlerJsep::processIceMessage( |
| 156 const WebKit::WebICECandidateDescriptor& candidate) { |
| 157 scoped_ptr<webrtc::IceCandidateInterface> native_candidate( |
| 158 dependency_factory_->CreateIceCandidate( |
| 159 UTF16ToUTF8(candidate.label()), |
| 160 UTF16ToUTF8(candidate.candidateLine()))); |
| 161 if (!native_candidate.get()) { |
| 162 LOG(ERROR) << "Could not create native ICE candidate"; |
| 163 return false; |
| 164 } |
| 165 |
| 166 bool return_value = |
| 167 native_peer_connection_->ProcessIceMessage(native_candidate.get()); |
| 168 if (!return_value) |
| 169 LOG(ERROR) << "Error processing ICE message"; |
| 170 return return_value; |
| 171 } |
| 172 |
| 173 void PeerConnectionHandlerJsep::addStream( |
| 174 const WebKit::WebMediaStreamDescriptor& stream) { |
| 175 AddStream(stream); |
| 176 native_peer_connection_->CommitStreamChanges(); |
| 177 } |
| 178 |
| 179 void PeerConnectionHandlerJsep::removeStream( |
| 180 const WebKit::WebMediaStreamDescriptor& stream) { |
| 181 RemoveStream(stream); |
| 182 native_peer_connection_->CommitStreamChanges(); |
| 183 } |
| 184 |
| 185 void PeerConnectionHandlerJsep::stop() { |
| 186 // TODO(ronghuawu): There's an issue with signaling messages being sent during |
| 187 // close. We need to investigate further. Not calling Close() on native |
| 188 // PeerConnection is OK for now. |
| 189 native_peer_connection_ = NULL; |
| 190 media_stream_impl_->ClosePeerConnection(this); |
| 191 } |
| 192 |
| 193 void PeerConnectionHandlerJsep::OnError() { |
| 194 // TODO(grunell): Implement. |
| 195 NOTIMPLEMENTED(); |
| 196 } |
| 197 |
| 198 void PeerConnectionHandlerJsep::OnMessage(const std::string& msg) { |
| 199 // TODO(grunell): Implement. |
| 200 NOTIMPLEMENTED(); |
| 201 } |
| 202 |
| 203 void PeerConnectionHandlerJsep::OnSignalingMessage(const std::string& msg) { |
| 204 // Not used by JSEP PeerConnection. |
| 205 NOTREACHED(); |
| 206 } |
| 207 |
| 208 void PeerConnectionHandlerJsep::OnStateChange(StateType state_changed) { |
| 209 switch (state_changed) { |
| 210 case kReadyState: |
| 211 WebKit::WebPeerConnection00HandlerClient::ReadyState ready_state; |
| 212 switch (native_peer_connection_->ready_state()) { |
| 213 case webrtc::PeerConnectionInterface::kNew: |
| 214 ready_state = WebKit::WebPeerConnection00HandlerClient::ReadyStateNew; |
| 215 break; |
| 216 case webrtc::PeerConnectionInterface::kNegotiating: |
| 217 ready_state = |
| 218 WebKit::WebPeerConnection00HandlerClient::ReadyStateNegotiating; |
| 219 break; |
| 220 case webrtc::PeerConnectionInterface::kActive: |
| 221 ready_state = |
| 222 WebKit::WebPeerConnection00HandlerClient::ReadyStateActive; |
| 223 break; |
| 224 case webrtc::PeerConnectionInterface::kClosing: |
| 225 // Not used by JSEP. |
| 226 NOTREACHED(); |
| 227 return; |
| 228 case webrtc::PeerConnectionInterface::kClosed: |
| 229 ready_state = |
| 230 WebKit::WebPeerConnection00HandlerClient::ReadyStateClosed; |
| 231 break; |
| 232 default: |
| 233 NOTREACHED(); |
| 234 return; |
| 235 } |
| 236 client_->didChangeReadyState(ready_state); |
| 237 break; |
| 238 case kIceState: |
| 239 // TODO(grunell): Implement when available in native PeerConnection. |
| 240 NOTIMPLEMENTED(); |
| 241 break; |
| 242 case kSdpState: |
| 243 // Not used by JSEP. |
| 244 NOTREACHED(); |
| 245 break; |
| 246 default: |
| 247 NOTREACHED(); |
| 248 break; |
| 249 } |
| 250 } |
| 251 |
| 252 void PeerConnectionHandlerJsep::OnAddStream( |
| 253 webrtc::MediaStreamInterface* stream) { |
| 254 if (!stream) |
| 255 return; |
| 256 |
| 257 DCHECK(remote_streams_.find(stream) == remote_streams_.end()); |
| 258 WebKit::WebMediaStreamDescriptor descriptor = |
| 259 CreateWebKitStreamDescriptor(stream); |
| 260 remote_streams_.insert( |
| 261 std::pair<webrtc::MediaStreamInterface*, |
| 262 WebKit::WebMediaStreamDescriptor>(stream, descriptor)); |
| 263 client_->didAddRemoteStream(descriptor); |
| 264 } |
| 265 |
| 266 void PeerConnectionHandlerJsep::OnRemoveStream( |
| 267 webrtc::MediaStreamInterface* stream) { |
| 268 if (!stream) |
| 269 return; |
| 270 |
| 271 RemoteStreamMap::iterator it = remote_streams_.find(stream); |
| 272 if (it == remote_streams_.end()) { |
| 273 NOTREACHED() << "Stream not found"; |
| 274 return; |
| 275 } |
| 276 WebKit::WebMediaStreamDescriptor descriptor = it->second; |
| 277 DCHECK(!descriptor.isNull()); |
| 278 remote_streams_.erase(it); |
| 279 client_->didRemoveRemoteStream(descriptor); |
| 280 } |
| 281 |
| 282 void PeerConnectionHandlerJsep::OnIceCandidate( |
| 283 const webrtc::IceCandidateInterface* candidate) { |
| 284 WebKit::WebICECandidateDescriptor web_candidate; |
| 285 |
| 286 std::string label = candidate->label(); |
| 287 std::string sdp; |
| 288 if (!candidate->ToString(&sdp)) { |
| 289 LOG(ERROR) << "Could not get SDP string"; |
| 290 return; |
| 291 } |
| 292 |
| 293 web_candidate.initialize(UTF8ToUTF16(label), UTF8ToUTF16(sdp)); |
| 294 |
| 295 // moreToFollow parameter isn't supported in native PeerConnection, so we |
| 296 // always use true here, and then false in OnIceComplete(). |
| 297 client_->didGenerateICECandidate(web_candidate, true); |
| 298 } |
| 299 |
| 300 void PeerConnectionHandlerJsep::OnIceComplete() { |
| 301 // moreToFollow parameter isn't supported in native PeerConnection, so we |
| 302 // send an empty WebIseCandidate with moreToFollow=false. |
| 303 WebKit::WebICECandidateDescriptor web_candidate; |
| 304 client_->didGenerateICECandidate(web_candidate, false); |
| 305 } |
| 306 |
| 307 webrtc::SessionDescriptionInterface* |
| 308 PeerConnectionHandlerJsep::CreateNativeSessionDescription( |
| 309 const WebKit::WebSessionDescriptionDescriptor& description) { |
| 310 std::string initial_sdp = UTF16ToUTF8(description.initialSDP()); |
| 311 webrtc::SessionDescriptionInterface* native_desc = |
| 312 dependency_factory_->CreateSessionDescription(initial_sdp); |
| 313 if (!native_desc) { |
| 314 LOG(ERROR) << "Failed to create native session description"; |
| 315 return NULL; |
| 316 } |
| 317 |
| 318 for (size_t i = 0; i < description.numberOfAddedCandidates(); ++i) { |
| 319 WebKit::WebICECandidateDescriptor candidate = description.candidate(i); |
| 320 scoped_ptr<webrtc::IceCandidateInterface> native_candidate( |
| 321 dependency_factory_->CreateIceCandidate( |
| 322 UTF16ToUTF8(candidate.label()), |
| 323 UTF16ToUTF8(candidate.candidateLine()))); |
| 324 if (!native_desc->AddCandidate(native_candidate.get())) |
| 325 LOG(ERROR) << "Failed to add candidate to native session description"; |
| 326 } |
| 327 |
| 328 return native_desc; |
| 329 } |
| 330 |
| 331 WebKit::WebSessionDescriptionDescriptor |
| 332 PeerConnectionHandlerJsep::CreateWebKitSessionDescription( |
| 333 const webrtc::SessionDescriptionInterface* native_desc) { |
| 334 WebKit::WebSessionDescriptionDescriptor description; |
| 335 if (!native_desc) { |
| 336 VLOG(1) << "Native session description is null"; |
| 337 return description; |
| 338 } |
| 339 |
| 340 std::string sdp; |
| 341 if (!native_desc->ToString(&sdp)) { |
| 342 LOG(ERROR) << "Failed to get SDP string of native session description"; |
| 343 return description; |
| 344 } |
| 345 |
| 346 description.initialize(UTF8ToUTF16(sdp)); |
| 347 return description; |
| 348 } |
| 349 |
| 350 bool PeerConnectionHandlerJsep::GetNativeAction( |
| 351 const Action action, |
| 352 webrtc::PeerConnectionInterface::Action* native_action) { |
| 353 switch (action) { |
| 354 case ActionSDPOffer: |
| 355 *native_action = webrtc::PeerConnectionInterface::kOffer; |
| 356 break; |
| 357 case ActionSDPPRanswer: |
| 358 VLOG(1) << "Action PRANSWER not supported yet"; |
| 359 return false; |
| 360 case ActionSDPAnswer: |
| 361 *native_action = webrtc::PeerConnectionInterface::kAnswer; |
| 362 break; |
| 363 default: |
| 364 NOTREACHED(); |
| 365 return false; |
| 366 } |
| 367 return true; |
| 368 } |
OLD | NEW |