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); | |
tommi (sloooow) - chröme
2012/09/13 14:48:45
nit: can skip this since it's dereferenced right a
| |
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 |