Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: content/renderer/media/media_stream_impl.cc

Issue 8060055: Adding support for MediaStream and PeerConnection functionality (Closed) Base URL: http://git.chromium.org/chromium/chromium.git@trunk
Patch Set: Code review, adding dependency factory, adding unit test, misc updates Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/media_stream_impl.h" 5 #include "content/renderer/media/media_stream_impl.h"
6 6
7 #include "base/string_util.h" 7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/utf_string_conversions.h"
12 #include "content/common/media/media_stream_options.h"
8 #include "content/renderer/media/capture_video_decoder.h" 13 #include "content/renderer/media/capture_video_decoder.h"
14 #include "content/renderer/media/media_stream_dependency_factory.h"
15 #include "content/renderer/media/media_stream_dispatcher.h"
16 #include "content/renderer/media/rtc_video_decoder.h"
9 #include "content/renderer/media/video_capture_impl_manager.h" 17 #include "content/renderer/media/video_capture_impl_manager.h"
10 #include "googleurl/src/gurl.h" 18 #include "content/renderer/media/video_capture_module_impl.h"
19 #include "content/renderer/media/webrtc_audio_device_impl.h"
20 #include "content/renderer/p2p/ipc_network_manager.h"
21 #include "content/renderer/p2p/ipc_socket_factory.h"
22 #include "content/renderer/p2p/socket_dispatcher.h"
23 #include "jingle/glue/thread_wrapper.h"
11 #include "media/base/message_loop_factory.h" 24 #include "media/base/message_loop_factory.h"
12 #include "media/base/pipeline.h" 25 #include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h"
26 #include "third_party/libjingle/source/talk/session/phone/dummydevicemanager.h"
27 #include "third_party/libjingle/source/talk/session/phone/webrtcmediaengine.h"
28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebLocalMediaStream.h "
30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStream.h"
31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamControl ler.h"
32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistr y.h"
33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamTrack.h "
34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamTrackLi st.h"
35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
37 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
38
39 // TODO(grunell): Replace NewRunnableMethod with base::Bind throughout this
40 // class.
13 41
14 namespace { 42 namespace {
15 43
16 static const int kVideoCaptureWidth = 352; 44 static const int kVideoCaptureWidth = 352;
17 static const int kVideoCaptureHeight = 288; 45 static const int kVideoCaptureHeight = 288;
18 static const int kVideoCaptureFramePerSecond = 30; 46 static const int kVideoCaptureFramePerSecond = 30;
19 47
20 static const int kStartOpenSessionId = 1;
21
22 // TODO(wjia): remove this string when full media stream code is checked in.
23 static const char kRawMediaScheme[] = "mediastream";
24
25 } // namespace 48 } // namespace
26 49
27 MediaStreamImpl::MediaStreamImpl(VideoCaptureImplManager* vc_manager) 50 MediaStreamImpl::MediaStreamImpl(
28 : vc_manager_(vc_manager) { 51 MediaStreamDispatcher* media_stream_dispatcher,
29 } 52 content::P2PSocketDispatcher* p2p_socket_dispatcher,
30 53 VideoCaptureImplManager* vc_manager,
31 MediaStreamImpl::~MediaStreamImpl() {} 54 MediaStreamDependencyFactory* dependency_factory)
55 : dependency_factory_(dependency_factory),
56 media_stream_dispatcher_(media_stream_dispatcher),
57 media_engine_(NULL),
58 p2p_socket_dispatcher_(p2p_socket_dispatcher),
59 vc_manager_(vc_manager),
60 signaling_thread_(NULL),
61 worker_thread_(NULL),
62 chrome_worker_thread_("Chrome_libJingle_WorkerThread"),
63 call_state_(NOT_STARTED),
64 vcm_created_(false) {
65 message_loop_proxy_ = base::MessageLoopProxy::current();
66 }
67
68 MediaStreamImpl::~MediaStreamImpl() {
69 if (native_peer_connection_.get()) {
70 native_peer_connection_->RegisterObserver(NULL);
71 native_peer_connection_->Close();
72 }
73 dependency_factory_->DeletePeerConnectionFactory();
74 }
75
76 void MediaStreamImpl::setController(
77 WebKit::WebMediaStreamController* controller) {
78 controller_.reset(controller);
79 }
80
81 void MediaStreamImpl::shutdown() {
82 controller_.reset();
83 }
84
85 void MediaStreamImpl::generateStream(
86 int request_id,
87 WebKit::WebGenerateStreamOptionFlags flags,
88 const WebKit::WebSecurityOrigin& web_security_origin) {
89 bool audio = (flags & WebKit::WebGenerateStreamRequestAudio) != 0;
90 media_stream::StreamOptions::VideoOption video_option =
91 media_stream::StreamOptions::kNoCamera;
92 if ((flags & WebKit::WebGenerateStreamRequestVideoFacingUser) &&
93 (flags & WebKit::WebGenerateStreamRequestVideoFacingEnvironment)) {
94 video_option = media_stream::StreamOptions::kFacingBoth;
95 } else {
96 if (flags & WebKit::WebGenerateStreamRequestVideoFacingEnvironment)
97 video_option = media_stream::StreamOptions::kFacingEnvironment;
98 if (flags & WebKit::WebGenerateStreamRequestVideoFacingUser)
99 video_option = media_stream::StreamOptions::kFacingUser;
100 }
101 DLOG(INFO) << "MediaStreamImpl::generateStream("
102 << request_id << ", [ "
103 << (audio ? "audio " : "")
104 << ((flags & WebKit::WebGenerateStreamRequestVideoFacingUser) ?
105 "video_facing_user " : "")
106 << ((flags &
107 WebKit::WebGenerateStreamRequestVideoFacingEnvironment) ?
108 "video_facing_environment " : "")
109 << "], "
110 << static_cast<string16>(web_security_origin.toString()) << ")";
111
112 media_stream_dispatcher_->GenerateStream(request_id, this,
113 media_stream::StreamOptions(audio, video_option),
114 UTF16ToUTF8(web_security_origin.toString()));
115 }
116
117 void MediaStreamImpl::stopGeneratedStream(
118 const WebKit::WebLocalMediaStream& stream) {
119 std::string label = UTF16ToUTF8(stream.label());
120 media_stream_dispatcher_->StopStream(label);
121 }
122
123 void MediaStreamImpl::recordStream(
124 const WebKit::WebMediaStreamRecorder& recorder) {
125 // TODO(grunell): Implement.
126 }
127
128 void MediaStreamImpl::getRecordedData(
129 const WebKit::WebMediaStreamRecorder& recorder,
130 int request_id) {
131 // TODO(grunell): Implement.
132 }
133
134 void MediaStreamImpl::disposeRecordedData(
135 const WebKit::WebMediaStreamRecorder& recorder) {
136 // TODO(grunell): Implement.
137 }
138
139 void MediaStreamImpl::setMediaStreamTrackEnabled(
140 const WebKit::WebMediaStreamTrack& track) {
141 // TODO(grunell): Implement.
142 }
143
144 void MediaStreamImpl::processSignalingMessage(
145 const WebKit::WebPeerConnection& web_peer_connection,
146 const WebKit::WebString& message) {
147 if (web_peer_connection != web_peer_connection_) {
148 DLOG(ERROR) << __FUNCTION__ << ": PeerConnection is not valid";
149 return;
150 }
151 DCHECK(native_peer_connection_.get());
152 native_peer_connection_->SignalingMessage(UTF16ToUTF8(message));
153 }
154
155 void MediaStreamImpl::message(
156 const WebKit::WebPeerConnection& web_peer_connection,
157 const WebKit::WebString& message) {
158 if (web_peer_connection != web_peer_connection_) {
159 DLOG(ERROR) << __FUNCTION__ << ": PeerConnection is not valid";
tommi (sloooow) - chröme 2011/10/25 09:58:34 NOTREACHED() instead of DLOG(ERROR)? (same for oth
Henrik Grunell 2011/10/25 12:14:32 Agree, changed.
160 return;
161 }
162 // TODO(grunell): Implement.
163 }
164
165 void MediaStreamImpl::addStream(
166 const WebKit::WebPeerConnection& web_peer_connection,
167 const WebKit::WebMediaStream& stream) {
168 if (web_peer_connection != web_peer_connection_) {
169 DLOG(ERROR) << __FUNCTION__ << ": PeerConnection is not valid";
170 return;
171 }
172 // TODO(grunell): Fix code in this function after a new native PeerConnection
173 // version has been rolled out.
174 std::string label = UTF16ToUTF8(stream.label());
175 if (call_state_ == NOT_STARTED) {
176 DCHECK(native_peer_connection_.get());
177 // TODO(grunell): Add audio and/or video depending on what's enabled
178 // in the stream.
179 std::string audioLabel = label;
180 audioLabel.append("-audio");
181 native_peer_connection_->AddStream(audioLabel, false); // Audio
182 native_peer_connection_->AddStream(label, true); // Video
183 call_state_ = INITIATING;
184 }
185 if (call_state_ == INITIATING || call_state_ == RECEIVING) {
186 local_label_ = label;
187 if (!vcm_created_) {
188 // Set the capture device
189 // TODO(grunell): Instead of using the first track, the selected track
190 // should be used.
191 int id = media_stream_dispatcher_->video_session_id(local_label_, 0);
192 if (id != media_stream::StreamDeviceInfo::kNoId) {
193 webrtc::VideoCaptureModule* vcm =
194 new VideoCaptureModuleImpl(id, vc_manager_.get());
195 vcm_created_ = true;
196 media_engine_->SetVideoCaptureModule(vcm);
197 native_peer_connection_->SetVideoCapture("");
198 }
199 }
200 if (call_state_ == INITIATING)
201 native_peer_connection_->Connect();
202 else if (call_state_ == RECEIVING)
203 call_state_ = SENDING_AND_RECEIVING;
204 } else {
205 DLOG(ERROR) << __FUNCTION__ << ": Multiple calls not supported";
206 return;
tommi (sloooow) - chröme 2011/10/25 09:58:34 no need for this return
Henrik Grunell 2011/10/25 12:14:32 Done.
207 }
208 }
209
210 void MediaStreamImpl::newPeerConnection(
211 const WebKit::WebPeerConnection& web_peer_connection,
212 const WebKit::WebString& configuration) {
213 if (native_peer_connection_.get()) {
214 LOG(WARNING) << __FUNCTION__ << ": A PeerConnection already exists";
215 return;
216 }
217
218 if (!media_engine_) {
219 media_engine_ = dependency_factory_->CreateWebRtcMediaEngine();
220 }
221
222 if (!signaling_thread_) {
223 jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
224 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
225 signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
226 }
227
228 if (!worker_thread_) {
229 if (!chrome_worker_thread_.IsRunning()) {
230 if (!chrome_worker_thread_.Start()) {
231 LOG(ERROR) << __FUNCTION__ << ": Could not start worker thread";
232 return;
233 }
234 }
235 base::WaitableEvent event(true, false);
236 chrome_worker_thread_.message_loop()->PostTask(
237 FROM_HERE,
238 NewRunnableMethod(this,
239 &MediaStreamImpl::InitializeWorkerThread,
240 &worker_thread_,
241 &event));
242 event.Wait();
243 DCHECK(worker_thread_);
244 }
245
246 if (!dependency_factory_->PeerConnectionFactoryCreated()) {
247 ipc_network_manager_.reset(
248 new content::IpcNetworkManager(p2p_socket_dispatcher_));
249 ipc_socket_factory_.reset(
250 new content::IpcPacketSocketFactory(p2p_socket_dispatcher_));
251 cricket::HttpPortAllocator* port_allocator =
252 new cricket::HttpPortAllocator(ipc_network_manager_.get(),
253 ipc_socket_factory_.get(),
254 "PeerConnection");
255 // TODO(mallinath): The following flags were added to solve a crash in
256 // HttpClient, we should probably remove them after that issue has been
257 // investigated.
258 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
259 cricket::PORTALLOCATOR_DISABLE_RELAY);
260
261 // TODO(mallinath): PeerConnectionFactory constructor changed in latest
262 // code and it no more accepts config string. Config string must be parsed
263 // here and set in HttpPortAllocator. Now using standard google STUN server
264 // address.
265 std::vector<talk_base::SocketAddress> stun_hosts;
266 stun_hosts.push_back(talk_base::SocketAddress("stun.l.google.com", 19302));
267 port_allocator->SetStunHosts(stun_hosts);
268
269 if (!dependency_factory_->CreatePeerConnectionFactory(
270 port_allocator,
271 media_engine_,
272 worker_thread_)) {
273 LOG(ERROR) << __FUNCTION__
274 << ": Could not initialize PeerConnection factory";
275 return;
tommi (sloooow) - chröme 2011/10/25 09:58:34 no need for this return statement
Henrik Grunell 2011/10/25 12:14:32 Kept, code below should not be executed.
276 }
277 }
278
279 native_peer_connection_.reset(dependency_factory_->CreatePeerConnection(
280 signaling_thread_));
281 DCHECK(native_peer_connection_.get());
282 web_peer_connection_ = web_peer_connection;
283 native_peer_connection_->RegisterObserver(this);
284 }
285
286 void MediaStreamImpl::closePeerConnection(
287 const WebKit::WebPeerConnection& web_peer_connection) {
288 if (web_peer_connection != web_peer_connection_) {
289 DLOG(ERROR) << __FUNCTION__ << ": PeerConnection is not valid";
290 return;
291 }
292 if (native_peer_connection_.get())
tommi (sloooow) - chröme 2011/10/25 09:58:34 did you forget {}?
Henrik Grunell 2011/10/25 12:14:32 No {}. Decreased indent below.
293 native_peer_connection_->RegisterObserver(NULL);
294 native_peer_connection_.reset();
295 web_peer_connection_.reset();
296 rtc_video_decoder_ = NULL;
297 media_engine_->SetVideoCaptureModule(NULL);
298 vcm_created_ = false;
299 call_state_ = NOT_STARTED;
300 }
301
302 void MediaStreamImpl::startNegotiation(
303 const WebKit::WebPeerConnection& web_peer_connection) {
304 if (web_peer_connection != web_peer_connection_) {
305 DLOG(ERROR) << __FUNCTION__ << ": PeerConnection is not valid";
306 return;
307 }
308 // TODO(grunell): Implement. Currently not supported in native PeerConnection.
309 }
310
311 void MediaStreamImpl::removeStream(
312 const WebKit::WebPeerConnection& web_peer_connection,
313 const WebKit::WebMediaStream& stream) {
314 if (web_peer_connection != web_peer_connection_) {
315 DLOG(ERROR) << __FUNCTION__ << ": PeerConnection is not valid";
316 return;
317 }
318 // TODO(grunell): Implement. Currently not supported in native PeerConnection.
319 }
320
321 void MediaStreamImpl::commitStreamChanges(
322 const WebKit::WebPeerConnection& web_peer_connection) {
323 if (web_peer_connection != web_peer_connection_) {
324 DLOG(ERROR) << __FUNCTION__ << ": PeerConnection is not valid";
325 return;
326 }
327 // TODO(grunell): Implement. Currently not supported in native PeerConnection.
328 }
32 329
33 scoped_refptr<media::VideoDecoder> MediaStreamImpl::GetVideoDecoder( 330 scoped_refptr<media::VideoDecoder> MediaStreamImpl::GetVideoDecoder(
34 const GURL& url, media::MessageLoopFactory* message_loop_factory) { 331 const GURL& url,
35 bool raw_media = (url.spec().find(kRawMediaScheme) == 0); 332 media::MessageLoopFactory* message_loop_factory) {
36 media::VideoDecoder* decoder = NULL; 333 std::string label =
37 if (raw_media) { 334 UTF16ToUTF8(WebKit::WebMediaStreamRegistry::mediaStreamLabel(url));
335 if (label.empty())
336 return NULL; // This is not a valid stream.
337
338 scoped_refptr<media::VideoDecoder> decoder;
339 if (media_stream_dispatcher_->IsStream(label)) {
340 // It's a local stream.
341 int video_session_id = media_stream_dispatcher_->video_session_id(label, 0);
38 media::VideoCapture::VideoCaptureCapability capability; 342 media::VideoCapture::VideoCaptureCapability capability;
39 capability.width = kVideoCaptureWidth; 343 capability.width = kVideoCaptureWidth;
40 capability.height = kVideoCaptureHeight; 344 capability.height = kVideoCaptureHeight;
41 capability.max_fps = kVideoCaptureFramePerSecond; 345 capability.max_fps = kVideoCaptureFramePerSecond;
42 capability.expected_capture_delay = 0; 346 capability.expected_capture_delay = 0;
43 capability.raw_type = media::VideoFrame::I420; 347 capability.raw_type = media::VideoFrame::I420;
44 capability.interlaced = false; 348 capability.interlaced = false;
45 capability.resolution_fixed = false; 349 capability.resolution_fixed = false;
46
47 decoder = new CaptureVideoDecoder( 350 decoder = new CaptureVideoDecoder(
48 message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoder").get(), 351 message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoderThread"),
49 kStartOpenSessionId, vc_manager_.get(), capability); 352 video_session_id,
353 vc_manager_.get(),
354 capability);
355 } else {
356 // It's a remote stream.
357 size_t found = label.rfind("-remote");
358 if (found != std::string::npos)
359 label = label.substr(0, found);
360 if (rtc_video_decoder_.get()) {
361 // The renderer is used by PeerConnection, release it first.
362 if (native_peer_connection_.get())
363 native_peer_connection_->SetVideoRenderer(label, NULL);
364 }
365 rtc_video_decoder_ = new RTCVideoDecoder(
366 message_loop_factory->GetMessageLoop("RtcVideoDecoderThread"),
367 url.spec());
368 decoder = rtc_video_decoder_;
369 if (native_peer_connection_.get())
370 native_peer_connection_->SetVideoRenderer(label, rtc_video_decoder_);
50 } 371 }
51 return decoder; 372 return decoder;
52 } 373 }
374
375 void MediaStreamImpl::OnStreamGenerated(
376 int request_id,
377 const std::string& label,
378 const media_stream::StreamDeviceInfoArray& audio_array,
379 const media_stream::StreamDeviceInfoArray& video_array) {
380 DCHECK(controller_.get());
381
382 WebKit::WebVector<WebKit::WebMediaStreamTrack> web_track_vector(
383 audio_array.size() + video_array.size());
384
385 WebKit::WebString track_id(WebKit::WebString::fromUTF8(""));
386 WebKit::WebString track_kind(WebKit::WebString::fromUTF8("main"));
387 WebKit::WebString track_label_audio(
388 WebKit::WebString::fromUTF8("AudioDevice"));
389 WebKit::WebString track_label_video(
390 WebKit::WebString::fromUTF8("VideoCapture"));
391 unsigned int track_num = web_track_vector.size();
tommi (sloooow) - chröme 2011/10/25 09:58:34 size_t?
Henrik Grunell 2011/10/25 12:14:32 Done.
392 while (track_num--) {
393 if (track_num < audio_array.size()) {
394 web_track_vector[track_num].initialize(track_id,
395 track_kind,
396 track_label_audio);
397 } else {
398 web_track_vector[track_num].initialize(track_id,
399 track_kind,
400 track_label_video);
401 }
402 }
403
404 WebKit::WebMediaStreamTrackList web_track_list;
405 web_track_list.initialize(web_track_vector);
406
407 WebKit::WebLocalMediaStream web_local_media_stream;
408 web_local_media_stream.initialize(UTF8ToUTF16(label), web_track_list);
409
410 controller_->streamGenerated(request_id, web_local_media_stream);
411 }
412
413 void MediaStreamImpl::OnStreamGenerationFailed(int request_id) {
414 VLOG(1) << "MediaStreamImpl::OnStreamGenerationFailed("
415 << request_id << ")";
416 DCHECK(controller_.get());
417 controller_->streamGenerationFailed(
418 request_id,
419 WebKit::WebMediaStreamController::ErrorPermissionDenied);
420 }
421
422 void MediaStreamImpl::OnVideoDeviceFailed(const std::string& label,
423 int index) {
424 VLOG(1) << "MediaStreamImpl::OnVideoDeviceFailed("
425 << label << ", " << index << ")";
426 DCHECK(controller_.get());
427 controller_->streamFailed(UTF8ToUTF16(label));
428 }
429
430 void MediaStreamImpl::OnAudioDeviceFailed(const std::string& label,
431 int index) {
432 VLOG(1) << "MediaStreamImpl::OnAudioDeviceFailed("
433 << label << ", " << index << ")";
434 DCHECK(controller_.get());
435 controller_->streamFailed(UTF8ToUTF16(label));
436 }
437
438 void MediaStreamImpl::OnSignalingMessage(const std::string& msg) {
439 if (!message_loop_proxy_->BelongsToCurrentThread()) {
440 message_loop_proxy_->PostTask(
441 FROM_HERE,
442 NewRunnableMethod(this, &MediaStreamImpl::OnSignalingMessage, msg));
443 return;
444 }
445
446 DCHECK(controller_.get());
447 controller_->onSignalingMessage(web_peer_connection_, UTF8ToUTF16(msg));
448 }
449
450 void MediaStreamImpl::OnAddStream(const std::string& stream_id, bool video) {
451 // TODO(grunell): Fix code in this function after a new native PeerConnection
452 // version has been rolled out.
453 if (video) {
454 if (call_state_ == NOT_STARTED) {
455 remote_label_ = stream_id;
456 call_state_ = RECEIVING;
457 } else if (call_state_ == INITIATING) {
458 remote_label_ = local_label_;
459 remote_label_ += "-remote";
460 call_state_ = SENDING_AND_RECEIVING;
461 }
462
463 if (!message_loop_proxy_->BelongsToCurrentThread()) {
464 message_loop_proxy_->PostTask(
465 FROM_HERE,
466 NewRunnableMethod(this,
467 &MediaStreamImpl::OnAddStreamCallback,
468 remote_label_));
469 return;
tommi (sloooow) - chröme 2011/10/25 09:58:34 no need for return
Henrik Grunell 2011/10/25 12:14:32 Done.
470 } else {
471 OnAddStreamCallback(remote_label_);
472 }
473 }
474 }
475
476 void MediaStreamImpl::OnRemoveStream(const std::string& stream_id, bool video) {
477 if (video) {
478 if (!message_loop_proxy_->BelongsToCurrentThread()) {
479 message_loop_proxy_->PostTask(
480 FROM_HERE,
481 NewRunnableMethod(this,
482 &MediaStreamImpl::OnRemoveStreamCallback,
483 remote_label_));
484 return;
tommi (sloooow) - chröme 2011/10/25 09:58:34 no need for return
Henrik Grunell 2011/10/25 12:14:32 Done.
485 } else {
486 OnRemoveStreamCallback(remote_label_);
487 }
488 }
489 }
490
491 void MediaStreamImpl::OnAddStreamCallback(const std::string& stream_label) {
492 DCHECK(controller_.get());
493
494 // Currently only support for one track
495 size_t size = 1;
496 WebKit::WebVector<WebKit::WebMediaStreamTrack> web_track_vector(size);
497 web_track_vector[0].initialize(WebKit::WebString::fromUTF8(""),
498 WebKit::WebString::fromUTF8("main"),
499 WebKit::WebString::fromUTF8(stream_label));
500 WebKit::WebMediaStreamTrackList web_track_list;
501 web_track_list.initialize(web_track_vector);
502
503 WebKit::WebMediaStream web_media_stream;
504 web_media_stream.initialize(UTF8ToUTF16(stream_label), web_track_list);
505
506 controller_->onAddStream(web_peer_connection_, web_media_stream);
507 }
508
509 void MediaStreamImpl::OnRemoveStreamCallback(const std::string& stream_label) {
510 DCHECK(controller_.get());
511 controller_->onRemoveStream(web_peer_connection_, UTF8ToUTF16(stream_label));
512 }
513
514 void MediaStreamImpl::InitializeWorkerThread(talk_base::Thread** thread,
515 base::WaitableEvent* event) {
516 jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
517 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
518 *thread = jingle_glue::JingleThreadWrapper::current();
519 event->Signal();
520 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698