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