OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #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" | 14 #include "content/renderer/media/media_stream_dependency_factory.h" |
15 #include "content/renderer/media/media_stream_dispatcher.h" | 15 #include "content/renderer/media/media_stream_dispatcher.h" |
16 #include "content/renderer/media/peer_connection_handler.h" | 16 #include "content/renderer/media/peer_connection_handler.h" |
| 17 #include "content/renderer/media/peer_connection_handler_jsep.h" |
17 #include "content/renderer/media/video_capture_impl_manager.h" | 18 #include "content/renderer/media/video_capture_impl_manager.h" |
18 #include "content/renderer/media/video_capture_module_impl.h" | 19 #include "content/renderer/media/video_capture_module_impl.h" |
19 #include "content/renderer/media/webrtc_audio_device_impl.h" | 20 #include "content/renderer/media/webrtc_audio_device_impl.h" |
20 #include "content/renderer/p2p/ipc_network_manager.h" | 21 #include "content/renderer/p2p/ipc_network_manager.h" |
21 #include "content/renderer/p2p/ipc_socket_factory.h" | 22 #include "content/renderer/p2p/ipc_socket_factory.h" |
22 #include "content/renderer/p2p/socket_dispatcher.h" | 23 #include "content/renderer/p2p/socket_dispatcher.h" |
23 #include "jingle/glue/thread_wrapper.h" | 24 #include "jingle/glue/thread_wrapper.h" |
24 #include "media/base/message_loop_factory.h" | 25 #include "media/base/message_loop_factory.h" |
25 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStre
amDescriptor.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStre
amDescriptor.h" |
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistr
y.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistr
y.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 MediaStreamImpl::MediaStreamImpl( | 74 MediaStreamImpl::MediaStreamImpl( |
74 MediaStreamDispatcher* media_stream_dispatcher, | 75 MediaStreamDispatcher* media_stream_dispatcher, |
75 content::P2PSocketDispatcher* p2p_socket_dispatcher, | 76 content::P2PSocketDispatcher* p2p_socket_dispatcher, |
76 VideoCaptureImplManager* vc_manager, | 77 VideoCaptureImplManager* vc_manager, |
77 MediaStreamDependencyFactory* dependency_factory) | 78 MediaStreamDependencyFactory* dependency_factory) |
78 : dependency_factory_(dependency_factory), | 79 : dependency_factory_(dependency_factory), |
79 media_stream_dispatcher_(media_stream_dispatcher), | 80 media_stream_dispatcher_(media_stream_dispatcher), |
80 p2p_socket_dispatcher_(p2p_socket_dispatcher), | 81 p2p_socket_dispatcher_(p2p_socket_dispatcher), |
81 network_manager_(NULL), | 82 network_manager_(NULL), |
82 vc_manager_(vc_manager), | 83 vc_manager_(vc_manager), |
83 peer_connection_handler_(NULL), | |
84 message_loop_proxy_(base::MessageLoopProxy::current()), | |
85 signaling_thread_(NULL), | 84 signaling_thread_(NULL), |
86 worker_thread_(NULL), | 85 worker_thread_(NULL), |
87 chrome_worker_thread_("Chrome_libJingle_WorkerThread") { | 86 chrome_worker_thread_("Chrome_libJingle_WorkerThread") { |
88 } | 87 } |
89 | 88 |
90 MediaStreamImpl::~MediaStreamImpl() { | 89 MediaStreamImpl::~MediaStreamImpl() { |
91 DCHECK(!peer_connection_handler_); | 90 DCHECK(peer_connection_handlers_.empty()); |
92 if (dependency_factory_.get()) | 91 if (dependency_factory_.get()) |
93 dependency_factory_->ReleasePeerConnectionFactory(); | 92 dependency_factory_->ReleasePeerConnectionFactory(); |
94 if (network_manager_) { | 93 if (network_manager_) { |
95 // The network manager needs to free its resources on the thread they were | 94 // The network manager needs to free its resources on the thread they were |
96 // created, which is the worked thread. | 95 // created, which is the worked thread. |
97 if (chrome_worker_thread_.IsRunning()) { | 96 if (chrome_worker_thread_.IsRunning()) { |
98 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 97 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
99 &MediaStreamImpl::DeleteIpcNetworkManager, | 98 &MediaStreamImpl::DeleteIpcNetworkManager, |
100 base::Unretained(this))); | 99 base::Unretained(this))); |
101 // Stopping the thread will wait until all tasks have been | 100 // Stopping the thread will wait until all tasks have been |
102 // processed before returning. We wait for the above task to finish before | 101 // processed before returning. We wait for the above task to finish before |
103 // letting the destructor continue to avoid any potential race issues. | 102 // letting the destructor continue to avoid any potential race issues. |
104 chrome_worker_thread_.Stop(); | 103 chrome_worker_thread_.Stop(); |
105 } else { | 104 } else { |
106 NOTREACHED() << "Worker thread not running."; | 105 NOTREACHED() << "Worker thread not running."; |
107 } | 106 } |
108 } | 107 } |
109 } | 108 } |
110 | 109 |
111 WebKit::WebPeerConnectionHandler* MediaStreamImpl::CreatePeerConnectionHandler( | 110 WebKit::WebPeerConnectionHandler* MediaStreamImpl::CreatePeerConnectionHandler( |
112 WebKit::WebPeerConnectionHandlerClient* client) { | 111 WebKit::WebPeerConnectionHandlerClient* client) { |
113 DCHECK(CalledOnValidThread()); | 112 DCHECK(CalledOnValidThread()); |
114 if (peer_connection_handler_) { | |
115 DVLOG(1) << "A PeerConnection already exists"; | |
116 return NULL; | |
117 } | |
118 if (!EnsurePeerConnectionFactory()) | 113 if (!EnsurePeerConnectionFactory()) |
119 return NULL; | 114 return NULL; |
120 | 115 |
121 peer_connection_handler_ = new PeerConnectionHandler( | 116 PeerConnectionHandler* pc_handler = new PeerConnectionHandler( |
122 client, | 117 client, |
123 this, | 118 this, |
124 dependency_factory_.get()); | 119 dependency_factory_.get()); |
| 120 peer_connection_handlers_.push_back(pc_handler); |
125 | 121 |
126 return peer_connection_handler_; | 122 return pc_handler; |
127 } | 123 } |
128 | 124 |
129 void MediaStreamImpl::ClosePeerConnection() { | 125 WebKit::WebPeerConnection00Handler* |
| 126 MediaStreamImpl::CreatePeerConnectionHandlerJsep( |
| 127 WebKit::WebPeerConnection00HandlerClient* client) { |
130 DCHECK(CalledOnValidThread()); | 128 DCHECK(CalledOnValidThread()); |
131 video_renderer_ = NULL; | 129 if (!EnsurePeerConnectionFactory()) |
132 peer_connection_handler_ = NULL; | 130 return NULL; |
133 // TODO(grunell): This is a temporary workaround for an error in native | 131 |
134 // PeerConnection where added live tracks are not seen on the remote side. | 132 PeerConnectionHandlerJsep* pc_handler = new PeerConnectionHandlerJsep( |
135 MediaStreamTrackPtrMap::const_iterator it = local_tracks_.begin(); | 133 client, |
136 for (; it != local_tracks_.end(); ++it) | 134 this, |
137 it->second->set_state(webrtc::MediaStreamTrackInterface::kEnded); | 135 dependency_factory_.get()); |
| 136 peer_connection_handlers_.push_back(pc_handler); |
| 137 |
| 138 return pc_handler; |
| 139 } |
| 140 |
| 141 void MediaStreamImpl::ClosePeerConnection( |
| 142 PeerConnectionHandlerBase* pc_handler) { |
| 143 DCHECK(CalledOnValidThread()); |
| 144 VideoRendererMap::iterator vr_it = video_renderers_.begin(); |
| 145 while (vr_it != video_renderers_.end()) { |
| 146 if (vr_it->second.second == pc_handler) { |
| 147 video_renderers_.erase(vr_it++); |
| 148 } else { |
| 149 ++vr_it; |
| 150 } |
| 151 } |
| 152 peer_connection_handlers_.remove(pc_handler); |
138 } | 153 } |
139 | 154 |
140 webrtc::MediaStreamTrackInterface* MediaStreamImpl::GetLocalMediaStreamTrack( | 155 webrtc::MediaStreamTrackInterface* MediaStreamImpl::GetLocalMediaStreamTrack( |
141 const std::string& label) { | 156 const std::string& label) { |
142 DCHECK(CalledOnValidThread()); | 157 DCHECK(CalledOnValidThread()); |
143 MediaStreamTrackPtrMap::iterator it = local_tracks_.find(label); | 158 MediaStreamTrackPtrMap::iterator it = local_tracks_.find(label); |
144 if (it == local_tracks_.end()) | 159 if (it == local_tracks_.end()) |
145 return NULL; | 160 return NULL; |
146 MediaStreamTrackPtr stream = it->second; | 161 MediaStreamTrackPtr stream = it->second; |
147 return stream.get(); | 162 return stream.get(); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 capability.expected_capture_delay = 0; | 254 capability.expected_capture_delay = 0; |
240 capability.raw_type = media::VideoFrame::I420; | 255 capability.raw_type = media::VideoFrame::I420; |
241 capability.interlaced = false; | 256 capability.interlaced = false; |
242 decoder = new CaptureVideoDecoder( | 257 decoder = new CaptureVideoDecoder( |
243 message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoderThread"), | 258 message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoderThread"), |
244 video_session_id, | 259 video_session_id, |
245 vc_manager_.get(), | 260 vc_manager_.get(), |
246 capability); | 261 capability); |
247 } else { | 262 } else { |
248 // It's a remote stream. | 263 // It's a remote stream. |
249 if (!video_renderer_.get()) | 264 std::string desc_label = UTF16ToUTF8(descriptor.label()); |
250 video_renderer_ = new talk_base::RefCountedObject<VideoRendererWrapper>(); | 265 PeerConnectionHandlerBase* pc_handler = NULL; |
251 if (video_renderer_->renderer()) { | 266 std::list<PeerConnectionHandlerBase*>::iterator it; |
252 // The renderer is used by PeerConnection, release it first. | 267 for (it = peer_connection_handlers_.begin(); |
253 if (peer_connection_handler_) { | 268 it != peer_connection_handlers_.end(); ++it) { |
254 peer_connection_handler_->SetVideoRenderer( | 269 if ((*it)->HasStream(desc_label)) { |
255 UTF16ToUTF8(descriptor.label()), | 270 pc_handler = *it; |
256 NULL); | 271 break; |
257 } | 272 } |
258 video_renderer_->SetVideoDecoder(NULL); | |
259 } | 273 } |
| 274 DCHECK(it != peer_connection_handlers_.end()); |
| 275 // TODO(grunell): We are not informed when a renderer should be deleted. |
| 276 // When this has been fixed, ensure we delete it. For now, we hold on |
| 277 // to all renderers until a PeerConnectionHandler is closed or we are |
| 278 // deleted (then all renderers are deleted), so it sort of leaks. |
| 279 // TODO(grunell): There is no support for multiple decoders per stream, this |
| 280 // code will need to be updated when that is supported. |
| 281 talk_base::scoped_refptr<VideoRendererWrapper> video_renderer = |
| 282 new talk_base::RefCountedObject<VideoRendererWrapper>(); |
260 RTCVideoDecoder* rtc_video_decoder = new RTCVideoDecoder( | 283 RTCVideoDecoder* rtc_video_decoder = new RTCVideoDecoder( |
261 message_loop_factory->GetMessageLoop("RtcVideoDecoderThread"), | 284 message_loop_factory->GetMessageLoop("RtcVideoDecoderThread"), |
262 url.spec()); | 285 url.spec()); |
263 decoder = rtc_video_decoder; | 286 decoder = rtc_video_decoder; |
264 video_renderer_->SetVideoDecoder(rtc_video_decoder); | 287 video_renderer->SetVideoDecoder(rtc_video_decoder); |
265 if (peer_connection_handler_) { | 288 pc_handler->SetVideoRenderer(desc_label, video_renderer); |
266 peer_connection_handler_->SetVideoRenderer( | 289 video_renderers_.erase(desc_label); // Remove old renderer if exists. |
267 UTF16ToUTF8(descriptor.label()), | 290 video_renderers_.insert( |
268 video_renderer_); | 291 std::make_pair(desc_label, std::make_pair(video_renderer, pc_handler))); |
269 } | |
270 } | 292 } |
271 return decoder; | 293 return decoder; |
272 } | 294 } |
273 | 295 |
274 void MediaStreamImpl::OnStreamGenerated( | 296 void MediaStreamImpl::OnStreamGenerated( |
275 int request_id, | 297 int request_id, |
276 const std::string& label, | 298 const std::string& label, |
277 const media_stream::StreamDeviceInfoArray& audio_array, | 299 const media_stream::StreamDeviceInfoArray& audio_array, |
278 const media_stream::StreamDeviceInfoArray& video_array) { | 300 const media_stream::StreamDeviceInfoArray& video_array) { |
279 DCHECK(CalledOnValidThread()); | 301 DCHECK(CalledOnValidThread()); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 } | 506 } |
485 | 507 |
486 MediaStreamImpl::VideoRendererWrapper::VideoRendererWrapper() {} | 508 MediaStreamImpl::VideoRendererWrapper::VideoRendererWrapper() {} |
487 | 509 |
488 MediaStreamImpl::VideoRendererWrapper::~VideoRendererWrapper() {} | 510 MediaStreamImpl::VideoRendererWrapper::~VideoRendererWrapper() {} |
489 | 511 |
490 void MediaStreamImpl::VideoRendererWrapper::SetVideoDecoder( | 512 void MediaStreamImpl::VideoRendererWrapper::SetVideoDecoder( |
491 RTCVideoDecoder* decoder) { | 513 RTCVideoDecoder* decoder) { |
492 rtc_video_decoder_ = decoder; | 514 rtc_video_decoder_ = decoder; |
493 } | 515 } |
OLD | NEW |