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