Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_video_capturer_source.h" | 5 #include "content/renderer/media/media_stream_video_capturer_source.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | |
| 8 #include "base/location.h" | 9 #include "base/location.h" |
| 9 #include "content/renderer/media/video_capture_impl_manager.h" | 10 #include "content/renderer/media/video_capture_impl_manager.h" |
| 10 #include "content/renderer/render_thread_impl.h" | 11 #include "content/renderer/render_thread_impl.h" |
| 12 #include "media/base/bind_to_current_loop.h" | |
| 11 #include "media/base/video_frame.h" | 13 #include "media/base/video_frame.h" |
| 12 | 14 |
| 13 namespace { | 15 namespace { |
| 14 | 16 |
| 15 struct SourceVideoFormat { | 17 struct SourceVideoFormat { |
| 16 int width; | 18 int width; |
| 17 int height; | 19 int height; |
| 18 int frame_rate; | 20 int frame_rate; |
| 19 }; | 21 }; |
| 20 | 22 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 31 | 33 |
| 32 namespace content { | 34 namespace content { |
| 33 | 35 |
| 34 VideoCapturerDelegate::VideoCapturerDelegate( | 36 VideoCapturerDelegate::VideoCapturerDelegate( |
| 35 const StreamDeviceInfo& device_info) | 37 const StreamDeviceInfo& device_info) |
| 36 : session_id_(device_info.session_id), | 38 : session_id_(device_info.session_id), |
| 37 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE || | 39 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE || |
| 38 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE), | 40 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE), |
| 39 got_first_frame_(false) { | 41 got_first_frame_(false) { |
| 40 DVLOG(3) << "VideoCapturerDelegate::ctor"; | 42 DVLOG(3) << "VideoCapturerDelegate::ctor"; |
| 41 // RenderThreadImpl::current() may be NULL in testing. | 43 |
| 44 // NULL in unit test. | |
| 42 if (RenderThreadImpl::current()) { | 45 if (RenderThreadImpl::current()) { |
| 43 capture_engine_ = RenderThreadImpl::current()->video_capture_impl_manager() | 46 VideoCaptureImplManager* manager = |
| 44 ->UseDevice(device_info.session_id); | 47 RenderThreadImpl::current()->video_capture_impl_manager(); |
| 45 DCHECK(capture_engine_); | 48 if (manager) |
|
Ami GONE FROM CHROMIUM
2014/04/24 21:04:31
how can this fail?
(here and elsewhere below)
Alpha Left Google
2014/04/24 22:50:34
Ownership:
RenderThreadImpl owns Blink owns WebMe
| |
| 49 release_device_cb_ = manager->UseDevice(session_id_); | |
| 46 } | 50 } |
| 47 message_loop_proxy_ = base::MessageLoopProxy::current(); | |
| 48 } | 51 } |
| 49 | 52 |
| 50 VideoCapturerDelegate::~VideoCapturerDelegate() { | 53 VideoCapturerDelegate::~VideoCapturerDelegate() { |
| 51 DVLOG(3) << "VideoCapturerDelegate::dtor"; | 54 DVLOG(3) << "VideoCapturerDelegate::dtor"; |
| 52 DCHECK(new_frame_callback_.is_null()); | 55 DCHECK(new_frame_callback_.is_null()); |
| 56 if (!release_device_cb_.is_null()) | |
| 57 release_device_cb_.Run(); | |
| 53 } | 58 } |
| 54 | 59 |
| 55 void VideoCapturerDelegate::GetCurrentSupportedFormats( | 60 void VideoCapturerDelegate::GetCurrentSupportedFormats( |
| 56 int max_requested_width, | 61 int max_requested_width, |
| 57 int max_requested_height, | 62 int max_requested_height, |
| 58 const SupportedFormatsCallback& callback) { | 63 const VideoCaptureDeviceFormatsCB& callback) { |
| 59 DVLOG(3) << "GetCurrentSupportedFormats(" | 64 DVLOG(3) << "GetCurrentSupportedFormats(" |
| 60 << " { max_requested_height = " << max_requested_height << "})" | 65 << " { max_requested_height = " << max_requested_height << "})" |
| 61 << " { max_requested_width = " << max_requested_width << "})"; | 66 << " { max_requested_width = " << max_requested_width << "})"; |
| 62 | 67 |
| 63 if (is_screen_cast_) { | 68 if (is_screen_cast_) { |
| 64 media::VideoCaptureFormats formats; | 69 media::VideoCaptureFormats formats; |
| 65 const int width = max_requested_width ? | 70 const int width = max_requested_width ? |
| 66 max_requested_width : MediaStreamVideoSource::kDefaultWidth; | 71 max_requested_width : MediaStreamVideoSource::kDefaultWidth; |
| 67 const int height = max_requested_height ? | 72 const int height = max_requested_height ? |
| 68 max_requested_height : MediaStreamVideoSource::kDefaultHeight; | 73 max_requested_height : MediaStreamVideoSource::kDefaultHeight; |
| 69 formats.push_back( | 74 formats.push_back( |
| 70 media::VideoCaptureFormat( | 75 media::VideoCaptureFormat( |
| 71 gfx::Size(width, height), | 76 gfx::Size(width, height), |
| 72 MediaStreamVideoSource::kDefaultFrameRate, | 77 MediaStreamVideoSource::kDefaultFrameRate, |
| 73 media::PIXEL_FORMAT_I420)); | 78 media::PIXEL_FORMAT_I420)); |
| 74 callback.Run(formats); | 79 callback.Run(formats); |
| 75 return; | 80 return; |
| 76 } | 81 } |
| 77 | 82 |
| 83 if (!RenderThreadImpl::current()) | |
|
Ami GONE FROM CHROMIUM
2014/04/24 21:04:31
comment this is for tests (here and elsewhere belo
Alpha Left Google
2014/04/24 22:50:34
Done.
| |
| 84 return; | |
| 85 VideoCaptureImplManager* manager = | |
| 86 RenderThreadImpl::current()->video_capture_impl_manager(); | |
| 87 if (!manager) | |
| 88 return; | |
| 78 DCHECK(source_formats_callback_.is_null()); | 89 DCHECK(source_formats_callback_.is_null()); |
| 79 source_formats_callback_ = callback; | 90 source_formats_callback_ = callback; |
| 80 capture_engine_->GetDeviceFormatsInUse(base::Bind( | 91 manager->GetDeviceFormatsInUse( |
| 81 &VideoCapturerDelegate::OnDeviceFormatsInUseReceived, this)); | 92 session_id_, |
| 93 media::BindToCurrentLoop( | |
| 94 base::Bind( | |
| 95 &VideoCapturerDelegate::OnDeviceFormatsInUseReceived, this))); | |
| 82 } | 96 } |
| 83 | 97 |
| 84 void VideoCapturerDelegate::StartDeliver( | 98 void VideoCapturerDelegate::StartToDeliver( |
| 85 const media::VideoCaptureParams& params, | 99 const media::VideoCaptureParams& params, |
| 86 const NewFrameCallback& new_frame_callback, | 100 const VideoCaptureDeliverFrameCB& new_frame_callback, |
| 87 const StartedCallback& started_callback) { | 101 const StartedCallback& started_callback) { |
| 88 DCHECK(params.requested_format.IsValid()); | 102 DCHECK(params.requested_format.IsValid()); |
| 89 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 103 DCHECK(thread_checker_.CalledOnValidThread()); |
| 90 new_frame_callback_ = new_frame_callback; | 104 new_frame_callback_ = new_frame_callback; |
| 91 started_callback_ = started_callback; | 105 started_callback_ = started_callback; |
| 92 got_first_frame_ = false; | 106 got_first_frame_ = false; |
| 93 | 107 |
| 94 // Increase the reference count to ensure the object is not deleted until | 108 if (!RenderThreadImpl::current()) |
| 95 // it is unregistered in VideoCapturerDelegate::OnRemoved. | 109 return; |
| 96 AddRef(); | 110 VideoCaptureImplManager* manager = |
| 97 capture_engine_->StartCapture(this, params); | 111 RenderThreadImpl::current()->video_capture_impl_manager(); |
| 112 if (!manager) | |
| 113 return; | |
| 114 stop_capture_cb_ = | |
| 115 manager->StartCapture( | |
| 116 session_id_, | |
| 117 params, | |
| 118 media::BindToCurrentLoop(base::Bind( | |
| 119 &VideoCapturerDelegate::OnStateUpdateOnRenderThread, this)), | |
| 120 media::BindToCurrentLoop(base::Bind( | |
| 121 &VideoCapturerDelegate::OnFrameReadyOnRenderThread, this))); | |
| 98 } | 122 } |
| 99 | 123 |
| 100 void VideoCapturerDelegate::StopDeliver() { | 124 void VideoCapturerDelegate::StopDeliver() { |
| 101 // Immediately make sure we don't provide more frames. | 125 // Immediately make sure we don't provide more frames. |
| 102 DVLOG(3) << "VideoCapturerDelegate::StopDeliver()"; | 126 DVLOG(3) << "VideoCapturerDelegate::StopDeliver()"; |
| 103 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 127 DCHECK(thread_checker_.CalledOnValidThread()); |
| 104 capture_engine_->StopCapture(this); | 128 if (!stop_capture_cb_.is_null()) { |
| 129 base::ResetAndReturn(&stop_capture_cb_).Run(); | |
| 130 } | |
| 105 new_frame_callback_.Reset(); | 131 new_frame_callback_.Reset(); |
| 106 started_callback_.Reset(); | 132 started_callback_.Reset(); |
| 107 source_formats_callback_.Reset(); | 133 source_formats_callback_.Reset(); |
| 108 } | 134 } |
| 109 | 135 |
| 110 void VideoCapturerDelegate::OnStarted(media::VideoCapture* capture) { | |
| 111 DVLOG(3) << "VideoCapturerDelegate::OnStarted"; | |
| 112 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); | |
| 113 } | |
| 114 | |
| 115 void VideoCapturerDelegate::OnStopped(media::VideoCapture* capture) { | |
| 116 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); | |
| 117 } | |
| 118 | |
| 119 void VideoCapturerDelegate::OnPaused(media::VideoCapture* capture) { | |
| 120 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); | |
| 121 } | |
| 122 | |
| 123 void VideoCapturerDelegate::OnError(media::VideoCapture* capture, | |
| 124 int error_code) { | |
| 125 DVLOG(3) << "VideoCapturerDelegate::OnError"; | |
| 126 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); | |
| 127 message_loop_proxy_->PostTask( | |
| 128 FROM_HERE, | |
| 129 base::Bind(&VideoCapturerDelegate::OnErrorOnRenderThread, this, capture)); | |
| 130 } | |
| 131 | |
| 132 void VideoCapturerDelegate::OnRemoved(media::VideoCapture* capture) { | |
| 133 DVLOG(3) << " MediaStreamVideoCapturerSource::OnRemoved"; | |
| 134 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); | |
| 135 | |
| 136 // Balance the AddRef in StartDeliver. | |
| 137 // This means we are no longer registered as an event handler and can safely | |
| 138 // be deleted. | |
| 139 Release(); | |
| 140 } | |
| 141 | |
| 142 void VideoCapturerDelegate::OnFrameReady( | |
| 143 media::VideoCapture* capture, | |
| 144 const scoped_refptr<media::VideoFrame>& frame) { | |
| 145 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); | |
| 146 message_loop_proxy_->PostTask( | |
| 147 FROM_HERE, | |
| 148 base::Bind(&VideoCapturerDelegate::OnFrameReadyOnRenderThread, | |
| 149 this, | |
| 150 capture, | |
| 151 frame)); | |
| 152 } | |
| 153 | |
| 154 void VideoCapturerDelegate::OnFrameReadyOnRenderThread( | 136 void VideoCapturerDelegate::OnFrameReadyOnRenderThread( |
| 155 media::VideoCapture* capture, | 137 const scoped_refptr<media::VideoFrame>& frame, |
| 156 const scoped_refptr<media::VideoFrame>& frame) { | 138 const media::VideoCaptureFormat& format, |
| 139 const base::TimeTicks& timestamp) { | |
| 157 if (!got_first_frame_) { | 140 if (!got_first_frame_) { |
| 158 got_first_frame_ = true; | 141 got_first_frame_ = true; |
| 159 if (!started_callback_.is_null()) | 142 if (!started_callback_.is_null()) |
| 160 started_callback_.Run(true); | 143 started_callback_.Run(true); |
| 161 } | 144 } |
| 162 | 145 |
| 163 if (!new_frame_callback_.is_null()) { | 146 if (!new_frame_callback_.is_null()) { |
| 164 new_frame_callback_.Run(frame); | 147 new_frame_callback_.Run(frame, format, timestamp); |
| 165 } | 148 } |
| 166 } | 149 } |
| 167 | 150 |
| 168 void VideoCapturerDelegate::OnErrorOnRenderThread( | 151 void VideoCapturerDelegate::OnStateUpdateOnRenderThread( |
| 169 media::VideoCapture* capture) { | 152 VideoCaptureState state) { |
| 170 if (!started_callback_.is_null()) | 153 if (state == VIDEO_CAPTURE_STATE_ERROR && !started_callback_.is_null()) { |
| 171 started_callback_.Run(false); | 154 started_callback_.Run(false); |
| 155 } | |
| 172 } | 156 } |
| 173 | 157 |
| 174 void VideoCapturerDelegate::OnDeviceFormatsInUseReceived( | 158 void VideoCapturerDelegate::OnDeviceFormatsInUseReceived( |
| 175 const media::VideoCaptureFormats& formats_in_use) { | 159 const media::VideoCaptureFormats& formats_in_use) { |
| 176 DVLOG(3) << "OnDeviceFormatsInUseReceived: " << formats_in_use.size(); | 160 DVLOG(3) << "OnDeviceFormatsInUseReceived: " << formats_in_use.size(); |
| 177 DCHECK(message_loop_proxy_ == base::MessageLoopProxy::current()); | 161 DCHECK(thread_checker_.CalledOnValidThread()); |
| 178 // StopDeliver() might have destroyed |source_formats_callback_| before | 162 // StopDeliver() might have destroyed |source_formats_callback_| before |
| 179 // arriving here. | 163 // arriving here. |
| 180 if (source_formats_callback_.is_null()) | 164 if (source_formats_callback_.is_null()) |
| 181 return; | 165 return; |
| 182 if (!formats_in_use.empty()) { | 166 if (!formats_in_use.empty()) { |
| 183 source_formats_callback_.Run(formats_in_use); | 167 source_formats_callback_.Run(formats_in_use); |
| 184 source_formats_callback_.Reset(); | 168 source_formats_callback_.Reset(); |
| 185 } else { | 169 return; |
| 186 // If there are no formats in use, try to retrieve the whole list of | |
| 187 // supported formats. | |
| 188 capture_engine_->GetDeviceSupportedFormats(base::Bind( | |
| 189 &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated, this)); | |
| 190 } | 170 } |
| 171 | |
| 172 // If there are no formats in use, try to retrieve the whole list of | |
| 173 // supported formats. | |
| 174 if (!RenderThreadImpl::current()) | |
| 175 return; | |
| 176 VideoCaptureImplManager* manager = | |
| 177 RenderThreadImpl::current()->video_capture_impl_manager(); | |
| 178 if (!manager) | |
| 179 return; | |
| 180 manager->GetDeviceSupportedFormats( | |
| 181 session_id_, | |
| 182 media::BindToCurrentLoop( | |
| 183 base::Bind( | |
| 184 &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated, | |
| 185 this))); | |
| 191 } | 186 } |
| 192 | 187 |
| 193 void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated( | 188 void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated( |
| 194 const media::VideoCaptureFormats& formats) { | 189 const media::VideoCaptureFormats& formats) { |
| 195 DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size() | 190 DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size() |
| 196 << " received"; | 191 << " received"; |
| 197 DCHECK(message_loop_proxy_ == base::MessageLoopProxy::current()); | 192 DCHECK(thread_checker_.CalledOnValidThread()); |
| 198 // StopDeliver() might have destroyed |source_formats_callback_| before | 193 // StopDeliver() might have destroyed |source_formats_callback_| before |
| 199 // arriving here. | 194 // arriving here. |
| 200 if (source_formats_callback_.is_null()) | 195 if (source_formats_callback_.is_null()) |
| 201 return; | 196 return; |
| 202 if (formats.size()) { | 197 if (formats.size()) { |
| 203 source_formats_callback_.Run(formats); | 198 source_formats_callback_.Run(formats); |
| 204 } else { | 199 } else { |
| 205 // The capture device doesn't seem to support capability enumeration, | 200 // The capture device doesn't seem to support capability enumeration, |
| 206 // compose a fallback list of capabilities. | 201 // compose a fallback list of capabilities. |
| 207 media::VideoCaptureFormats default_formats; | 202 media::VideoCaptureFormats default_formats; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 base::Unretained(this))); | 234 base::Unretained(this))); |
| 240 } | 235 } |
| 241 | 236 |
| 242 void MediaStreamVideoCapturerSource::StartSourceImpl( | 237 void MediaStreamVideoCapturerSource::StartSourceImpl( |
| 243 const media::VideoCaptureParams& params) { | 238 const media::VideoCaptureParams& params) { |
| 244 media::VideoCaptureParams new_params(params); | 239 media::VideoCaptureParams new_params(params); |
| 245 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE || | 240 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE || |
| 246 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { | 241 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { |
| 247 new_params.allow_resolution_change = true; | 242 new_params.allow_resolution_change = true; |
| 248 } | 243 } |
| 249 delegate_->StartDeliver( | 244 delegate_->StartToDeliver( |
| 250 new_params, | 245 new_params, |
| 251 base::Bind(&MediaStreamVideoCapturerSource::DeliverVideoFrame, | 246 base::Bind(&MediaStreamVideoCapturerSource::DeliverVideoFrame, |
| 252 base::Unretained(this)), | 247 base::Unretained(this)), |
| 253 base::Bind(&MediaStreamVideoCapturerSource::OnStartDone, | 248 base::Bind(&MediaStreamVideoCapturerSource::OnStartDone, |
| 254 base::Unretained(this))); | 249 base::Unretained(this))); |
| 255 } | 250 } |
| 256 | 251 |
| 257 void MediaStreamVideoCapturerSource::StopSourceImpl() { | 252 void MediaStreamVideoCapturerSource::StopSourceImpl() { |
| 258 delegate_->StopDeliver(); | 253 delegate_->StopDeliver(); |
| 259 } | 254 } |
| 260 | 255 |
| 261 } // namespace content | 256 } // namespace content |
| OLD | NEW |