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/browser/media/capture/content_video_capture_device_core.h" | 5 #include "content/browser/media/capture/content_video_capture_device_core.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/callback_forward.h" | 9 #include "base/callback_forward.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
14 #include "base/message_loop/message_loop_proxy.h" | 14 #include "base/message_loop/message_loop_proxy.h" |
15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
16 #include "base/sequenced_task_runner.h" | 16 #include "base/sequenced_task_runner.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
19 #include "base/synchronization/lock.h" | 19 #include "base/synchronization/lock.h" |
20 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
21 #include "base/threading/thread_checker.h" | 21 #include "base/threading/thread_checker.h" |
22 #include "base/time/time.h" | 22 #include "base/time/time.h" |
23 #include "base/trace_event/trace_event.h" | 23 #include "base/trace_event/trace_event.h" |
24 #include "content/public/browser/browser_thread.h" | |
25 #include "media/base/bind_to_current_loop.h" | 24 #include "media/base/bind_to_current_loop.h" |
26 #include "media/base/video_capture_types.h" | 25 #include "media/base/video_capture_types.h" |
27 #include "media/base/video_frame.h" | 26 #include "media/base/video_frame.h" |
28 #include "media/base/video_frame_metadata.h" | 27 #include "media/base/video_frame_metadata.h" |
29 #include "media/base/video_util.h" | 28 #include "media/base/video_util.h" |
30 #include "ui/gfx/geometry/rect.h" | 29 #include "ui/gfx/geometry/rect.h" |
31 | 30 |
32 namespace content { | 31 namespace content { |
33 | 32 |
34 namespace { | 33 namespace { |
35 | 34 |
36 void DeleteCaptureMachineOnUIThread( | 35 void DeleteCaptureMachine( |
37 scoped_ptr<VideoCaptureMachine> capture_machine) { | 36 scoped_ptr<VideoCaptureMachine> capture_machine) { |
38 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
39 | |
40 capture_machine.reset(); | 37 capture_machine.reset(); |
41 } | 38 } |
42 | 39 |
43 } // namespace | 40 } // namespace |
44 | 41 |
45 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( | 42 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( |
46 scoped_ptr<media::VideoCaptureDevice::Client> client, | 43 scoped_ptr<media::VideoCaptureDevice::Client> client, |
47 const media::VideoCaptureParams& params) | 44 const media::VideoCaptureParams& params) |
48 : client_(client.Pass()), | 45 : client_(client.Pass()), |
49 oracle_(base::TimeDelta::FromMicroseconds( | 46 oracle_(base::TimeDelta::FromMicroseconds( |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 } | 241 } |
245 | 242 |
246 media::VideoCaptureParams new_params = params; | 243 media::VideoCaptureParams new_params = params; |
247 // Frame dimensions must each be an even integer since the client wants (or | 244 // Frame dimensions must each be an even integer since the client wants (or |
248 // will convert to) YUV420. | 245 // will convert to) YUV420. |
249 new_params.requested_format.frame_size.SetSize( | 246 new_params.requested_format.frame_size.SetSize( |
250 MakeEven(params.requested_format.frame_size.width()), | 247 MakeEven(params.requested_format.frame_size.width()), |
251 MakeEven(params.requested_format.frame_size.height())); | 248 MakeEven(params.requested_format.frame_size.height())); |
252 | 249 |
253 oracle_proxy_ = new ThreadSafeCaptureOracle(client.Pass(), new_params); | 250 oracle_proxy_ = new ThreadSafeCaptureOracle(client.Pass(), new_params); |
254 | 251 capture_machine_->Start( |
255 // Starts the capture machine asynchronously. | 252 oracle_proxy_, |
256 BrowserThread::PostTaskAndReplyWithResult( | 253 new_params, |
257 BrowserThread::UI, | |
258 FROM_HERE, | |
259 base::Bind(&VideoCaptureMachine::Start, | |
260 base::Unretained(capture_machine_.get()), | |
261 oracle_proxy_, | |
262 new_params), | |
263 base::Bind(&ContentVideoCaptureDeviceCore::CaptureStarted, AsWeakPtr())); | 254 base::Bind(&ContentVideoCaptureDeviceCore::CaptureStarted, AsWeakPtr())); |
264 | 255 |
265 TransitionStateTo(kCapturing); | 256 TransitionStateTo(kCapturing); |
266 } | 257 } |
267 | 258 |
268 void ContentVideoCaptureDeviceCore::StopAndDeAllocate() { | 259 void ContentVideoCaptureDeviceCore::StopAndDeAllocate() { |
269 DCHECK(thread_checker_.CalledOnValidThread()); | 260 DCHECK(thread_checker_.CalledOnValidThread()); |
270 | 261 |
271 if (state_ != kCapturing) | 262 if (state_ != kCapturing) |
272 return; | 263 return; |
273 | 264 |
274 oracle_proxy_->Stop(); | 265 oracle_proxy_->Stop(); |
275 oracle_proxy_ = NULL; | 266 oracle_proxy_ = NULL; |
276 | 267 |
277 TransitionStateTo(kIdle); | 268 TransitionStateTo(kIdle); |
278 | 269 |
279 // Stops the capture machine asynchronously. | 270 capture_machine_->Stop(base::Bind(&base::DoNothing)); |
280 BrowserThread::PostTask( | |
281 BrowserThread::UI, FROM_HERE, base::Bind( | |
282 &VideoCaptureMachine::Stop, | |
283 base::Unretained(capture_machine_.get()), | |
284 base::Bind(&base::DoNothing))); | |
285 } | 271 } |
286 | 272 |
287 void ContentVideoCaptureDeviceCore::CaptureStarted(bool success) { | 273 void ContentVideoCaptureDeviceCore::CaptureStarted(bool success) { |
288 DCHECK(thread_checker_.CalledOnValidThread()); | 274 DCHECK(thread_checker_.CalledOnValidThread()); |
289 if (!success) { | 275 if (!success) { |
290 std::string reason("Failed to start capture machine."); | 276 std::string reason("Failed to start capture machine."); |
291 DVLOG(1) << reason; | 277 DVLOG(1) << reason; |
292 Error(reason); | 278 Error(reason); |
293 } | 279 } |
294 } | 280 } |
295 | 281 |
296 ContentVideoCaptureDeviceCore::ContentVideoCaptureDeviceCore( | 282 ContentVideoCaptureDeviceCore::ContentVideoCaptureDeviceCore( |
297 scoped_ptr<VideoCaptureMachine> capture_machine) | 283 scoped_ptr<VideoCaptureMachine> capture_machine) |
298 : state_(kIdle), | 284 : state_(kIdle), |
299 capture_machine_(capture_machine.Pass()) { | 285 capture_machine_(capture_machine.Pass()) { |
300 DCHECK(capture_machine_.get()); | 286 DCHECK(capture_machine_.get()); |
301 } | 287 } |
302 | 288 |
303 ContentVideoCaptureDeviceCore::~ContentVideoCaptureDeviceCore() { | 289 ContentVideoCaptureDeviceCore::~ContentVideoCaptureDeviceCore() { |
304 DCHECK(thread_checker_.CalledOnValidThread()); | 290 DCHECK(thread_checker_.CalledOnValidThread()); |
305 DCHECK_NE(state_, kCapturing); | 291 DCHECK_NE(state_, kCapturing); |
306 // If capture_machine is not NULL, then we need to return to the UI thread to | 292 // If capture_machine is not NULL, then we need to safely |
307 // safely stop the capture machine. | 293 // stop the capture machine. |
308 if (capture_machine_) { | 294 if (capture_machine_) { |
309 VideoCaptureMachine* capture_machine_ptr = capture_machine_.get(); | 295 capture_machine_->Stop(base::Bind(&DeleteCaptureMachine, |
310 BrowserThread::PostTask( | 296 base::Passed(&capture_machine_))); |
311 BrowserThread::UI, FROM_HERE, | |
312 base::Bind(&VideoCaptureMachine::Stop, | |
313 base::Unretained(capture_machine_ptr), | |
314 base::Bind(&DeleteCaptureMachineOnUIThread, | |
315 base::Passed(&capture_machine_)))); | |
316 } | 297 } |
317 DVLOG(1) << "ContentVideoCaptureDeviceCore@" << this << " destroying."; | 298 DVLOG(1) << "ContentVideoCaptureDeviceCore@" << this << " destroying."; |
318 } | 299 } |
319 | 300 |
320 void ContentVideoCaptureDeviceCore::TransitionStateTo(State next_state) { | 301 void ContentVideoCaptureDeviceCore::TransitionStateTo(State next_state) { |
321 DCHECK(thread_checker_.CalledOnValidThread()); | 302 DCHECK(thread_checker_.CalledOnValidThread()); |
322 | 303 |
323 #ifndef NDEBUG | 304 #ifndef NDEBUG |
324 static const char* kStateNames[] = { | 305 static const char* kStateNames[] = { |
325 "Idle", "Allocated", "Capturing", "Error" | 306 "Idle", "Allocated", "Capturing", "Error" |
(...skipping 12 matching lines...) Expand all Loading... |
338 return; | 319 return; |
339 | 320 |
340 if (oracle_proxy_.get()) | 321 if (oracle_proxy_.get()) |
341 oracle_proxy_->ReportError(reason); | 322 oracle_proxy_->ReportError(reason); |
342 | 323 |
343 StopAndDeAllocate(); | 324 StopAndDeAllocate(); |
344 TransitionStateTo(kError); | 325 TransitionStateTo(kError); |
345 } | 326 } |
346 | 327 |
347 } // namespace content | 328 } // namespace content |
OLD | NEW |