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" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 MediaStreamImpl::MediaStreamImpl( | 73 MediaStreamImpl::MediaStreamImpl( |
74 MediaStreamDispatcher* media_stream_dispatcher, | 74 MediaStreamDispatcher* media_stream_dispatcher, |
75 content::P2PSocketDispatcher* p2p_socket_dispatcher, | 75 content::P2PSocketDispatcher* p2p_socket_dispatcher, |
76 VideoCaptureImplManager* vc_manager, | 76 VideoCaptureImplManager* vc_manager, |
77 MediaStreamDependencyFactory* dependency_factory) | 77 MediaStreamDependencyFactory* dependency_factory) |
78 : dependency_factory_(dependency_factory), | 78 : dependency_factory_(dependency_factory), |
79 media_stream_dispatcher_(media_stream_dispatcher), | 79 media_stream_dispatcher_(media_stream_dispatcher), |
80 p2p_socket_dispatcher_(p2p_socket_dispatcher), | 80 p2p_socket_dispatcher_(p2p_socket_dispatcher), |
81 network_manager_(NULL), | 81 network_manager_(NULL), |
82 vc_manager_(vc_manager), | 82 vc_manager_(vc_manager), |
83 peer_connection_handler_(NULL), | |
84 message_loop_proxy_(base::MessageLoopProxy::current()), | |
85 signaling_thread_(NULL), | 83 signaling_thread_(NULL), |
86 worker_thread_(NULL), | 84 worker_thread_(NULL), |
87 chrome_worker_thread_("Chrome_libJingle_WorkerThread") { | 85 chrome_worker_thread_("Chrome_libJingle_WorkerThread") { |
88 } | 86 } |
89 | 87 |
90 MediaStreamImpl::~MediaStreamImpl() { | 88 MediaStreamImpl::~MediaStreamImpl() { |
91 DCHECK(!peer_connection_handler_); | 89 DCHECK(peer_connection_handlers_.empty()); |
92 if (dependency_factory_.get()) | 90 if (dependency_factory_.get()) |
93 dependency_factory_->ReleasePeerConnectionFactory(); | 91 dependency_factory_->ReleasePeerConnectionFactory(); |
94 if (network_manager_) { | 92 if (network_manager_) { |
95 // The network manager needs to free its resources on the thread they were | 93 // The network manager needs to free its resources on the thread they were |
96 // created, which is the worked thread. | 94 // created, which is the worked thread. |
97 if (chrome_worker_thread_.IsRunning()) { | 95 if (chrome_worker_thread_.IsRunning()) { |
98 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 96 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
99 &MediaStreamImpl::DeleteIpcNetworkManager, | 97 &MediaStreamImpl::DeleteIpcNetworkManager, |
100 base::Unretained(this))); | 98 base::Unretained(this))); |
101 // Stopping the thread will wait until all tasks have been | 99 // Stopping the thread will wait until all tasks have been |
102 // processed before returning. We wait for the above task to finish before | 100 // processed before returning. We wait for the above task to finish before |
103 // letting the destructor continue to avoid any potential race issues. | 101 // letting the destructor continue to avoid any potential race issues. |
104 chrome_worker_thread_.Stop(); | 102 chrome_worker_thread_.Stop(); |
105 } else { | 103 } else { |
106 NOTREACHED() << "Worker thread not running."; | 104 NOTREACHED() << "Worker thread not running."; |
107 } | 105 } |
108 } | 106 } |
109 } | 107 } |
110 | 108 |
111 WebKit::WebPeerConnectionHandler* MediaStreamImpl::CreatePeerConnectionHandler( | 109 WebKit::WebPeerConnectionHandler* MediaStreamImpl::CreatePeerConnectionHandler( |
112 WebKit::WebPeerConnectionHandlerClient* client) { | 110 WebKit::WebPeerConnectionHandlerClient* client) { |
113 DCHECK(CalledOnValidThread()); | 111 DCHECK(CalledOnValidThread()); |
114 if (peer_connection_handler_) { | |
115 DVLOG(1) << "A PeerConnection already exists"; | |
116 return NULL; | |
117 } | |
118 if (!EnsurePeerConnectionFactory()) | 112 if (!EnsurePeerConnectionFactory()) |
119 return NULL; | 113 return NULL; |
120 | 114 |
121 peer_connection_handler_ = new PeerConnectionHandler( | 115 PeerConnectionHandler* pc_handler = new PeerConnectionHandler( |
122 client, | 116 client, |
123 this, | 117 this, |
124 dependency_factory_.get()); | 118 dependency_factory_.get()); |
119 peer_connection_handlers_.push_back(pc_handler); | |
tommi (sloooow) - chröme
2012/02/29 13:37:00
maybe we should put a CHECK(pc_handler) here first
Henrik Grunell
2012/03/23 12:51:56
Crashing is not necessary at all actually. We won'
| |
125 | 120 |
126 return peer_connection_handler_; | 121 return pc_handler; |
127 } | 122 } |
128 | 123 |
129 void MediaStreamImpl::ClosePeerConnection() { | 124 void MediaStreamImpl::ClosePeerConnection(PeerConnectionHandler* pc_handler) { |
130 DCHECK(CalledOnValidThread()); | 125 DCHECK(CalledOnValidThread()); |
131 video_renderer_ = NULL; | 126 VideoRendererMap::iterator vr_it = video_renderers_.begin(); |
132 peer_connection_handler_ = NULL; | 127 while (vr_it != video_renderers_.end()) { |
128 if (vr_it->second.second == pc_handler) { | |
129 video_renderers_.erase(vr_it++); | |
tommi (sloooow) - chröme
2012/02/29 13:37:00
hmm... is it safe to continue using the iterator a
Henrik Grunell
2012/03/23 12:51:56
It is safe; post increment will be evaluated befor
| |
130 } else { | |
131 ++vr_it; | |
132 } | |
133 } | |
134 peer_connection_handlers_.remove(pc_handler); | |
133 // TODO(grunell): This is a temporary workaround for an error in native | 135 // TODO(grunell): This is a temporary workaround for an error in native |
134 // PeerConnection where added live tracks are not seen on the remote side. | 136 // PeerConnection where added live tracks are not seen on the remote side. |
135 MediaStreamTrackPtrMap::const_iterator it = local_tracks_.begin(); | 137 // If several PeerConnections are used, the tracks will be ended when the |
136 for (; it != local_tracks_.end(); ++it) | 138 // first PeerConnection is closed, which is an issue. The alternative (skip |
139 // this workaround) would mean that only one call could be made properly. | |
140 // When JSEP support is added this will be fixed in native PeerConnection. | |
141 for (MediaStreamTrackPtrMap::const_iterator it = local_tracks_.begin(); | |
142 it != local_tracks_.end(); ++it) { | |
137 it->second->set_state(webrtc::MediaStreamTrackInterface::kEnded); | 143 it->second->set_state(webrtc::MediaStreamTrackInterface::kEnded); |
144 } | |
138 } | 145 } |
139 | 146 |
140 webrtc::MediaStreamTrackInterface* MediaStreamImpl::GetLocalMediaStreamTrack( | 147 webrtc::MediaStreamTrackInterface* MediaStreamImpl::GetLocalMediaStreamTrack( |
141 const std::string& label) { | 148 const std::string& label) { |
142 DCHECK(CalledOnValidThread()); | 149 DCHECK(CalledOnValidThread()); |
143 MediaStreamTrackPtrMap::iterator it = local_tracks_.find(label); | 150 MediaStreamTrackPtrMap::iterator it = local_tracks_.find(label); |
144 if (it == local_tracks_.end()) | 151 if (it == local_tracks_.end()) |
145 return NULL; | 152 return NULL; |
146 MediaStreamTrackPtr stream = it->second; | 153 MediaStreamTrackPtr stream = it->second; |
147 return stream.get(); | 154 return stream.get(); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 capability.expected_capture_delay = 0; | 246 capability.expected_capture_delay = 0; |
240 capability.raw_type = media::VideoFrame::I420; | 247 capability.raw_type = media::VideoFrame::I420; |
241 capability.interlaced = false; | 248 capability.interlaced = false; |
242 decoder = new CaptureVideoDecoder( | 249 decoder = new CaptureVideoDecoder( |
243 message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoderThread"), | 250 message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoderThread"), |
244 video_session_id, | 251 video_session_id, |
245 vc_manager_.get(), | 252 vc_manager_.get(), |
246 capability); | 253 capability); |
247 } else { | 254 } else { |
248 // It's a remote stream. | 255 // It's a remote stream. |
249 if (!video_renderer_.get()) | 256 std::string desc_label = UTF16ToUTF8(descriptor.label()); |
250 video_renderer_ = new talk_base::RefCountedObject<VideoRendererWrapper>(); | 257 PeerConnectionHandler* pc_handler = NULL; |
251 if (video_renderer_->renderer()) { | 258 std::list<PeerConnectionHandler*>::iterator it; |
252 // The renderer is used by PeerConnection, release it first. | 259 for (it = peer_connection_handlers_.begin(); |
253 if (peer_connection_handler_) { | 260 it != peer_connection_handlers_.end(); ++it) { |
254 peer_connection_handler_->SetVideoRenderer( | 261 if ((*it)->HasStream(desc_label)) { |
255 UTF16ToUTF8(descriptor.label()), | 262 pc_handler = *it; |
256 NULL); | 263 break; |
257 } | 264 } |
258 video_renderer_->SetVideoDecoder(NULL); | |
259 } | 265 } |
266 // TODO(grunell): We are not informed when a renderer should be deleted. | |
tommi (sloooow) - chröme
2012/02/29 13:37:00
after the for loop, what about adding:
DCHECK_NE(i
Henrik Grunell
2012/03/23 12:51:56
We can't assume that. See comment below.
| |
267 // When this has been fixed, ensure we delete it. For now, we hold on | |
268 // to all renderers until a PeerConnectionHandler is closed or we are | |
269 // deleted (then all renderers are deleted), so it sort of leaks. | |
270 // TODO(grunell): There is no support for multiple renderers per stream in | |
271 // native PeerConnection, this code may need to be updated when that is | |
272 // supported. | |
273 talk_base::scoped_refptr<VideoRendererWrapper> video_renderer = | |
274 new talk_base::RefCountedObject<VideoRendererWrapper>(); | |
260 RTCVideoDecoder* rtc_video_decoder = new RTCVideoDecoder( | 275 RTCVideoDecoder* rtc_video_decoder = new RTCVideoDecoder( |
261 message_loop_factory->GetMessageLoop("RtcVideoDecoderThread"), | 276 message_loop_factory->GetMessageLoop("RtcVideoDecoderThread"), |
262 url.spec()); | 277 url.spec()); |
263 decoder = rtc_video_decoder; | 278 decoder = rtc_video_decoder; |
264 video_renderer_->SetVideoDecoder(rtc_video_decoder); | 279 video_renderer->SetVideoDecoder(rtc_video_decoder); |
265 if (peer_connection_handler_) { | 280 if (pc_handler) |
tommi (sloooow) - chröme
2012/02/29 13:37:00
in what situation will pc_handler be NULL?
Henrik Grunell
2012/03/23 12:51:56
It can be if a PeerConnection is closed and the js
Henrik Grunell
2012/03/26 05:04:26
Verified OK to return null ptr.
| |
266 peer_connection_handler_->SetVideoRenderer( | 281 pc_handler->SetVideoRenderer(desc_label, video_renderer); |
267 UTF16ToUTF8(descriptor.label()), | 282 video_renderers_.erase(desc_label); // Remove old renderer if exists. |
tommi (sloooow) - chröme
2012/02/29 13:37:00
is it conceivable that more than one renderer can
Henrik Grunell
2012/03/23 12:51:56
At the moment no, there shall be zero or one rende
| |
268 video_renderer_); | 283 video_renderers_.insert( |
269 } | 284 std::make_pair(desc_label, std::make_pair(video_renderer, pc_handler))); |
270 } | 285 } |
271 return decoder; | 286 return decoder; |
272 } | 287 } |
273 | 288 |
274 void MediaStreamImpl::OnStreamGenerated( | 289 void MediaStreamImpl::OnStreamGenerated( |
275 int request_id, | 290 int request_id, |
276 const std::string& label, | 291 const std::string& label, |
277 const media_stream::StreamDeviceInfoArray& audio_array, | 292 const media_stream::StreamDeviceInfoArray& audio_array, |
278 const media_stream::StreamDeviceInfoArray& video_array) { | 293 const media_stream::StreamDeviceInfoArray& video_array) { |
279 DCHECK(CalledOnValidThread()); | 294 DCHECK(CalledOnValidThread()); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 } | 486 } |
472 | 487 |
473 MediaStreamImpl::VideoRendererWrapper::VideoRendererWrapper() {} | 488 MediaStreamImpl::VideoRendererWrapper::VideoRendererWrapper() {} |
474 | 489 |
475 MediaStreamImpl::VideoRendererWrapper::~VideoRendererWrapper() {} | 490 MediaStreamImpl::VideoRendererWrapper::~VideoRendererWrapper() {} |
476 | 491 |
477 void MediaStreamImpl::VideoRendererWrapper::SetVideoDecoder( | 492 void MediaStreamImpl::VideoRendererWrapper::SetVideoDecoder( |
478 RTCVideoDecoder* decoder) { | 493 RTCVideoDecoder* decoder) { |
479 rtc_video_decoder_ = decoder; | 494 rtc_video_decoder_ = decoder; |
480 } | 495 } |
OLD | NEW |