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 NOTREACHED(); | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
nit: you can remove this since you have a default
perkj_chrome
2012/09/13 13:41:34
Done.
| |
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::WebRTCSessionDescription | |
73 CreateWebKitSessionDescription( | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
shouldn't this have zero indent like in other plac
perkj_chrome
2012/09/13 13:41:34
Done.
| |
74 const webrtc::SessionDescriptionInterface* native_desc) { | |
75 WebKit::WebRTCSessionDescription 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*/) { | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
remove /* */
perkj_chrome
2012/09/13 13:41:34
Done.
| |
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::WebRTCSessionDescription& 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::WebRTCSessionDescription& 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( | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
can you use Chrome's scoped_refptr instead?
(same
perkj_chrome
2012/09/13 13:41:34
Done.
| |
242 new talk_base::RefCountedObject<SetSessionDescriptionRequest>(request)); | |
243 native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc); | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
...and then you don't need the .get() calls
perkj_chrome
2012/09/13 13:41:34
Done.
| |
244 } | |
245 | |
246 WebKit::WebRTCSessionDescription | |
247 RTCPeerConnectionHandler::localDescription() { | |
248 const webrtc::SessionDescriptionInterface* native_desc = | |
249 native_peer_connection_->local_description(); | |
250 WebKit::WebRTCSessionDescription description = | |
251 CreateWebKitSessionDescription(native_desc); | |
252 return description; | |
253 } | |
254 | |
255 WebKit::WebRTCSessionDescription | |
256 RTCPeerConnectionHandler::remoteDescription() { | |
257 const webrtc::SessionDescriptionInterface* native_desc = | |
258 native_peer_connection_->remote_description(); | |
259 WebKit::WebRTCSessionDescription 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::WebRTCICECandidate& 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."; | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
use LOG_IF
perkj_chrome
2012/09/13 13:41:34
Done.
| |
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"; | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
should there just be a DCHECK at the top of the fu
perkj_chrome
2012/09/13 13:41:34
Done.
| |
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"; | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
DCHECK?
same for similar cases throughout
perkj_chrome
2012/09/13 13:41:34
Done.
| |
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::WebRTCICECandidate 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::WebRTCICECandidate web_candidate; | |
386 client_->didGenerateICECandidate(web_candidate); | |
387 } | |
388 | |
389 void RTCPeerConnectionHandler::OnRenegotiationNeeded() { | |
390 client_->negotiationNeeded(); | |
391 } | |
392 | |
393 webrtc::SessionDescriptionInterface* | |
394 RTCPeerConnectionHandler::CreateNativeSessionDescription( | |
395 const WebKit::WebRTCSessionDescription& 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) { | |
tommi (sloooow) - chröme
2012/09/13 12:20:14
remove this if+return and just do this instead:
L
perkj_chrome
2012/09/13 13:41:34
Done.
| |
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 |