OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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.h" | |
6 | |
7 #include <stdlib.h> | |
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/libjingle/source/talk/base/thread.h" | |
17 #include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h" | |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamDescrip tor.h" | |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamSource. h" | |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPeerConnectionHand lerClient.h" | |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" | |
22 | |
23 PeerConnectionHandler::PeerConnectionHandler( | |
24 WebKit::WebPeerConnectionHandlerClient* client, | |
25 MediaStreamImpl* msi, | |
26 MediaStreamDependencyFactory* dependency_factory, | |
27 talk_base::Thread* signaling_thread, | |
28 cricket::HttpPortAllocator* port_allocator) | |
29 : client_(client), | |
30 media_stream_impl_(msi), | |
31 dependency_factory_(dependency_factory), | |
32 message_loop_proxy_(base::MessageLoopProxy::current()), | |
33 signaling_thread_(signaling_thread), | |
34 port_allocator_(port_allocator), | |
35 call_state_(NOT_STARTED) { | |
36 } | |
37 | |
38 PeerConnectionHandler::~PeerConnectionHandler() { | |
39 if (native_peer_connection_.get()) { | |
40 native_peer_connection_->RegisterObserver(NULL); | |
41 native_peer_connection_->Close(); | |
42 } | |
43 } | |
44 | |
45 bool PeerConnectionHandler::SetVideoRenderer( | |
46 const std::string& stream_label, | |
47 cricket::VideoRenderer* renderer) { | |
48 return native_peer_connection_->SetVideoRenderer(stream_label, renderer); | |
49 } | |
50 | |
51 void PeerConnectionHandler::initialize( | |
52 const WebKit::WebString& server_configuration, | |
53 const WebKit::WebSecurityOrigin& security_origin) { | |
54 // We support the following server configuration format: | |
55 // "STUN <address>:<port>". We only support STUN at the moment. | |
56 | |
57 // Strip "STUN ". | |
58 std::string strip_string = "STUN "; | |
59 std::string config = UTF16ToUTF8(server_configuration); | |
60 size_t pos = config.find(strip_string); | |
61 DCHECK_EQ(pos, 0u); | |
scherkus (not reviewing)
2011/11/23 22:52:04
are these strings passed in from WebKit via JS/HTM
Henrik Grunell
2011/11/24 11:32:59
Yes.
| |
62 if (pos != 0) { | |
63 VLOG(1) << "Invalid configuration string."; | |
scherkus (not reviewing)
2011/11/23 22:52:04
DVLOG?
Henrik Grunell
2011/11/24 11:32:59
Sure, fixed.
| |
64 return; | |
65 } | |
66 config = config.substr(strip_string.length()); | |
67 // Parse out port. | |
68 pos = config.find(':'); | |
69 DCHECK(pos != std::string::npos); | |
scherkus (not reviewing)
2011/11/23 22:52:04
ditto for this + other DCHECKs
Henrik Grunell
2011/11/24 11:32:59
Done.
| |
70 if (pos == std::string::npos) { | |
71 VLOG(1) << "Invalid configuration string."; | |
72 return; | |
73 } | |
74 int port = 0; | |
75 bool success = base::StringToInt(config.substr(pos+1), &port); | |
76 DCHECK(success && (port != 0)); | |
77 if (!success || (port == 0)) { | |
78 VLOG(1) << "Invalid configuration string."; | |
79 return; | |
80 } | |
81 // Get address. | |
82 std::string address = config.substr(0, pos); | |
83 | |
84 std::vector<talk_base::SocketAddress> stun_hosts; | |
85 stun_hosts.push_back(talk_base::SocketAddress(address, port)); | |
86 port_allocator_->SetStunHosts(stun_hosts); | |
87 | |
88 native_peer_connection_.reset(dependency_factory_->CreatePeerConnection( | |
89 signaling_thread_)); | |
90 native_peer_connection_->RegisterObserver(this); | |
91 } | |
92 | |
93 void PeerConnectionHandler::produceInitialOffer( | |
94 const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>& | |
95 pending_add_streams) { | |
96 // We currently don't support creating an initial offer without a stream. | |
97 // Native PeerConnection will anyway create the initial offer when the first | |
98 // (and only) stream is added, so it will be done when processPendingStreams | |
99 // is called if not here. | |
100 if (pending_add_streams.isEmpty()) { | |
101 DVLOG(1) << "Can't produce initial offer with no stream."; | |
102 return; | |
103 } | |
104 // TODO(grunell): Support several streams. | |
105 DCHECK_EQ(pending_add_streams.size(), 1u); | |
106 WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector; | |
107 pending_add_streams[0].sources(source_vector); | |
108 DCHECK_GT(source_vector.size(), 0u); | |
109 std::string label = UTF16ToUTF8(source_vector[0].id()); | |
110 AddStream(label); | |
111 } | |
112 | |
113 void PeerConnectionHandler::handleInitialOffer(const WebKit::WebString& sdp) { | |
114 native_peer_connection_->SignalingMessage(UTF16ToUTF8(sdp)); | |
115 } | |
116 | |
117 void PeerConnectionHandler::processSDP(const WebKit::WebString& sdp) { | |
118 native_peer_connection_->SignalingMessage(UTF16ToUTF8(sdp)); | |
119 } | |
120 | |
121 void PeerConnectionHandler::processPendingStreams( | |
122 const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>& | |
123 pending_add_streams, | |
124 const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>& | |
125 pending_remove_streams) { | |
126 // TODO(grunell): Support several streams. | |
127 if (!pending_add_streams.isEmpty()) { | |
128 DCHECK_EQ(pending_add_streams.size(), 1u); | |
129 AddStream(UTF16ToUTF8(pending_add_streams[0].label())); | |
130 } | |
131 // Currently we ignore remove stream, no support in native PeerConnection. | |
132 } | |
133 | |
134 void PeerConnectionHandler::sendDataStreamMessage( | |
135 const char* data, | |
136 size_t length) { | |
137 // TODO(grunell): Implement. Not supported in native PeerConnection. | |
138 NOTIMPLEMENTED(); | |
139 } | |
140 | |
141 void PeerConnectionHandler::stop() { | |
142 if (native_peer_connection_.get()) | |
143 native_peer_connection_->RegisterObserver(NULL); | |
144 native_peer_connection_.reset(); | |
145 // The close function will delete us. | |
146 media_stream_impl_->ClosePeerConnection(); | |
147 } | |
148 | |
149 void PeerConnectionHandler::OnSignalingMessage(const std::string& msg) { | |
150 if (!message_loop_proxy_->BelongsToCurrentThread()) { | |
151 message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | |
152 &PeerConnectionHandler::OnSignalingMessage, | |
153 base::Unretained(this), | |
154 msg)); | |
155 return; | |
156 } | |
157 client_->didGenerateSDP(UTF8ToUTF16(msg)); | |
158 } | |
159 | |
160 void PeerConnectionHandler::OnAddStream(const std::string& stream_id, | |
161 bool video) { | |
162 if (!video) | |
163 return; | |
164 | |
165 if (!message_loop_proxy_->BelongsToCurrentThread()) { | |
166 message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | |
167 &PeerConnectionHandler::OnAddStreamCallback, | |
168 base::Unretained(this), | |
169 stream_id)); | |
170 } else { | |
171 OnAddStreamCallback(stream_id); | |
172 } | |
173 } | |
174 | |
175 void PeerConnectionHandler::OnRemoveStream( | |
176 const std::string& stream_id, | |
177 bool video) { | |
178 if (!video) | |
179 return; | |
180 | |
181 if (!message_loop_proxy_->BelongsToCurrentThread()) { | |
182 message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | |
183 &PeerConnectionHandler::OnRemoveStreamCallback, | |
184 base::Unretained(this), | |
185 remote_label_)); | |
186 } else { | |
187 OnRemoveStreamCallback(remote_label_); | |
188 } | |
189 } | |
190 | |
191 void PeerConnectionHandler::AddStream(const std::string label) { | |
192 // TODO(grunell): Fix code in this function after a new native PeerConnection | |
193 // version has been rolled out. | |
194 if (call_state_ == NOT_STARTED) { | |
195 // TODO(grunell): Add audio and/or video depending on what's enabled | |
196 // in the stream. | |
197 std::string audio_label = label; | |
198 audio_label.append("-audio"); | |
199 native_peer_connection_->AddStream(audio_label, false); // Audio | |
200 native_peer_connection_->AddStream(label, true); // Video | |
201 call_state_ = INITIATING; | |
202 } | |
203 if (call_state_ == INITIATING || call_state_ == RECEIVING) { | |
204 local_label_ = label; | |
205 if (media_stream_impl_->SetVideoCaptureModule(label)) | |
206 native_peer_connection_->SetVideoCapture(""); | |
207 if (call_state_ == INITIATING) | |
208 native_peer_connection_->Connect(); | |
209 else if (call_state_ == RECEIVING) | |
210 call_state_ = SENDING_AND_RECEIVING; | |
211 } else { | |
212 DLOG(ERROR) << "Multiple streams not supported"; | |
213 } | |
214 } | |
215 | |
216 void PeerConnectionHandler::OnAddStreamCallback( | |
217 const std::string& stream_label) { | |
218 // TODO(grunell): Fix code in this function after a new native PeerConnection | |
219 // version has been rolled out. | |
220 if (call_state_ == NOT_STARTED) { | |
221 remote_label_ = stream_label; | |
222 call_state_ = RECEIVING; | |
223 } else if (call_state_ == INITIATING) { | |
224 remote_label_ = local_label_; | |
225 remote_label_ += "-remote"; | |
226 call_state_ = SENDING_AND_RECEIVING; | |
227 } | |
228 | |
229 // TODO(grunell): Support several tracks. | |
230 WebKit::WebVector<WebKit::WebMediaStreamSource> | |
231 source_vector(static_cast<size_t>(2)); | |
232 source_vector[0].initialize(WebKit::WebString::fromUTF8(remote_label_), | |
233 WebKit::WebMediaStreamSource::TypeVideo, | |
234 WebKit::WebString::fromUTF8("RemoteVideo")); | |
235 source_vector[1].initialize(WebKit::WebString::fromUTF8(remote_label_), | |
236 WebKit::WebMediaStreamSource::TypeAudio, | |
237 WebKit::WebString::fromUTF8("RemoteAudio")); | |
238 WebKit::WebMediaStreamDescriptor descriptor; | |
239 descriptor.initialize(UTF8ToUTF16(remote_label_), source_vector); | |
240 client_->didAddRemoteStream(descriptor); | |
241 } | |
242 | |
243 void PeerConnectionHandler::OnRemoveStreamCallback( | |
244 const std::string& stream_label) { | |
245 // TODO(grunell): Support several tracks. | |
246 WebKit::WebVector<WebKit::WebMediaStreamSource> | |
247 source_vector(static_cast<size_t>(2)); | |
248 source_vector[0].initialize(WebKit::WebString::fromUTF8(stream_label), | |
249 WebKit::WebMediaStreamSource::TypeVideo, | |
250 WebKit::WebString::fromUTF8("RemoteVideo")); | |
251 source_vector[1].initialize(WebKit::WebString::fromUTF8(stream_label), | |
252 WebKit::WebMediaStreamSource::TypeAudio, | |
253 WebKit::WebString::fromUTF8("RemoteAudio")); | |
254 WebKit::WebMediaStreamDescriptor descriptor; | |
255 descriptor.initialize(UTF8ToUTF16(stream_label), source_vector); | |
256 client_->didRemoveRemoteStream(descriptor); | |
257 } | |
OLD | NEW |