Chromium Code Reviews| 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 // Implementation notes: This needs to work on a variety of hardware | 5 // Implementation notes: This needs to work on a variety of hardware |
| 6 // configurations where the speed of the CPU and GPU greatly affect overall | 6 // configurations where the speed of the CPU and GPU greatly affect overall |
| 7 // performance. Spanning several threads, the process of capturing has been | 7 // performance. Spanning several threads, the process of capturing has been |
| 8 // split up into four conceptual stages: | 8 // split up into four conceptual stages: |
| 9 // | 9 // |
| 10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's | 10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 } | 132 } |
| 133 | 133 |
| 134 // Thread-safe, refcounted proxy to the VideoCaptureOracle. This proxy wraps | 134 // Thread-safe, refcounted proxy to the VideoCaptureOracle. This proxy wraps |
| 135 // the VideoCaptureOracle, which decides which frames to capture, and a | 135 // the VideoCaptureOracle, which decides which frames to capture, and a |
| 136 // VideoCaptureDevice::Client, which allocates and receives the captured | 136 // VideoCaptureDevice::Client, which allocates and receives the captured |
| 137 // frames, in a lock to synchronize state between the two. | 137 // frames, in a lock to synchronize state between the two. |
| 138 class ThreadSafeCaptureOracle | 138 class ThreadSafeCaptureOracle |
| 139 : public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> { | 139 : public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> { |
| 140 public: | 140 public: |
| 141 ThreadSafeCaptureOracle(scoped_ptr<media::VideoCaptureDevice::Client> client, | 141 ThreadSafeCaptureOracle(scoped_ptr<media::VideoCaptureDevice::Client> client, |
| 142 scoped_ptr<VideoCaptureOracle> oracle); | 142 scoped_ptr<VideoCaptureOracle> oracle, |
| 143 const gfx::Size& capture_size); | |
| 143 | 144 |
| 144 bool ObserveEventAndDecideCapture( | 145 bool ObserveEventAndDecideCapture( |
| 145 VideoCaptureOracle::Event event, | 146 VideoCaptureOracle::Event event, |
| 146 base::Time event_time, | 147 base::Time event_time, |
| 147 scoped_refptr<media::VideoFrame>* storage, | 148 scoped_refptr<media::VideoFrame>* storage, |
| 148 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback); | 149 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback); |
| 149 | 150 |
| 150 base::TimeDelta capture_period() const { | 151 base::TimeDelta capture_period() const { |
| 151 return oracle_->capture_period(); | 152 return oracle_->capture_period(); |
| 152 } | 153 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 167 base::Time timestamp, | 168 base::Time timestamp, |
| 168 bool success); | 169 bool success); |
| 169 // Protects everything below it. | 170 // Protects everything below it. |
| 170 base::Lock lock_; | 171 base::Lock lock_; |
| 171 | 172 |
| 172 // Recipient of our capture activity. | 173 // Recipient of our capture activity. |
| 173 scoped_ptr<media::VideoCaptureDevice::Client> client_; | 174 scoped_ptr<media::VideoCaptureDevice::Client> client_; |
| 174 | 175 |
| 175 // Makes the decision to capture a frame. | 176 // Makes the decision to capture a frame. |
| 176 const scoped_ptr<VideoCaptureOracle> oracle_; | 177 const scoped_ptr<VideoCaptureOracle> oracle_; |
| 178 | |
| 179 // The resolution at which we're capturing. | |
| 180 const gfx::Size capture_size_; | |
| 177 }; | 181 }; |
| 178 | 182 |
| 179 // FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible | 183 // FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible |
| 180 // with RenderWidgetHostViewFrameSubscriber. We create one per event type. | 184 // with RenderWidgetHostViewFrameSubscriber. We create one per event type. |
| 181 class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber { | 185 class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber { |
| 182 public: | 186 public: |
| 183 FrameSubscriber(VideoCaptureOracle::Event event_type, | 187 FrameSubscriber(VideoCaptureOracle::Event event_type, |
| 184 const scoped_refptr<ThreadSafeCaptureOracle>& oracle) | 188 const scoped_refptr<ThreadSafeCaptureOracle>& oracle) |
| 185 : event_type_(event_type), | 189 : event_type_(event_type), |
| 186 oracle_proxy_(oracle) {} | 190 oracle_proxy_(oracle) {} |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 // verbose logging is turned on. | 393 // verbose logging is turned on. |
| 390 base::Time last_frame_rate_log_time_; | 394 base::Time last_frame_rate_log_time_; |
| 391 int count_frames_rendered_; | 395 int count_frames_rendered_; |
| 392 int last_frame_number_; | 396 int last_frame_number_; |
| 393 | 397 |
| 394 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog); | 398 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog); |
| 395 }; | 399 }; |
| 396 | 400 |
| 397 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( | 401 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( |
| 398 scoped_ptr<media::VideoCaptureDevice::Client> client, | 402 scoped_ptr<media::VideoCaptureDevice::Client> client, |
| 399 scoped_ptr<VideoCaptureOracle> oracle) | 403 scoped_ptr<VideoCaptureOracle> oracle, |
| 400 : client_(client.Pass()), oracle_(oracle.Pass()) {} | 404 const gfx::Size& capture_size) |
| 405 : client_(client.Pass()), | |
| 406 oracle_(oracle.Pass()), | |
| 407 capture_size_(capture_size) { | |
| 408 } | |
| 401 | 409 |
| 402 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( | 410 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( |
| 403 VideoCaptureOracle::Event event, | 411 VideoCaptureOracle::Event event, |
| 404 base::Time event_time, | 412 base::Time event_time, |
| 405 scoped_refptr<media::VideoFrame>* storage, | 413 scoped_refptr<media::VideoFrame>* storage, |
| 406 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) { | 414 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) { |
| 407 base::AutoLock guard(lock_); | 415 base::AutoLock guard(lock_); |
| 408 | 416 |
| 409 if (!client_) | 417 if (!client_) |
| 410 return false; // Capture is stopped. | 418 return false; // Capture is stopped. |
| 411 | 419 |
| 412 scoped_refptr<media::VideoFrame> output_buffer = | 420 scoped_refptr<media::VideoFrame> output_buffer = |
| 413 client_->ReserveOutputBuffer(); | 421 client_->ReserveOutputBuffer(capture_size_); |
| 414 const bool should_capture = | 422 const bool should_capture = |
| 415 oracle_->ObserveEventAndDecideCapture(event, event_time); | 423 oracle_->ObserveEventAndDecideCapture(event, event_time); |
| 416 const bool content_is_dirty = | 424 const bool content_is_dirty = |
| 417 (event == VideoCaptureOracle::kCompositorUpdate || | 425 (event == VideoCaptureOracle::kCompositorUpdate || |
| 418 event == VideoCaptureOracle::kSoftwarePaint); | 426 event == VideoCaptureOracle::kSoftwarePaint); |
| 419 const char* event_name = | 427 const char* event_name = |
| 420 (event == VideoCaptureOracle::kTimerPoll ? "poll" : | 428 (event == VideoCaptureOracle::kTimerPoll ? "poll" : |
| 421 (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" : | 429 (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" : |
| 422 "paint")); | 430 "paint")); |
| 423 | 431 |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1021 // wants (or will convert to) YUV420. | 1029 // wants (or will convert to) YUV420. |
| 1022 width = MakeEven(width); | 1030 width = MakeEven(width); |
| 1023 height = MakeEven(height); | 1031 height = MakeEven(height); |
| 1024 if (width < kMinFrameWidth || height < kMinFrameHeight) { | 1032 if (width < kMinFrameWidth || height < kMinFrameHeight) { |
| 1025 DVLOG(1) << "invalid width (" << width << ") and/or height (" | 1033 DVLOG(1) << "invalid width (" << width << ") and/or height (" |
| 1026 << height << ")"; | 1034 << height << ")"; |
| 1027 client->OnError(); | 1035 client->OnError(); |
| 1028 return; | 1036 return; |
| 1029 } | 1037 } |
| 1030 | 1038 |
| 1031 // Initialize capture settings which will be consistent for the | 1039 // Need to call OnFrameInfo just to set the frame rate. |
|
Ami GONE FROM CHROMIUM
2013/10/04 00:24:15
Time for a special-purpose setter?
ncarter (slow)
2013/10/16 02:08:40
I'm not quite sure what to do about frame_rate. It
Ami GONE FROM CHROMIUM
2013/10/17 20:31:45
I like #1 best, but I agree fixing this doesn't ne
ncarter (slow)
2013/10/22 01:06:20
Done.
| |
| 1032 // duration of the capture. | 1040 // The other parameters of this struct are ignored. |
| 1033 media::VideoCaptureCapability settings; | 1041 media::VideoCaptureCapability settings; |
| 1034 | |
| 1035 settings.width = width; | |
| 1036 settings.height = height; | |
| 1037 settings.frame_rate = frame_rate; | 1042 settings.frame_rate = frame_rate; |
| 1038 // Note: the value of |settings.color| doesn't matter if we use only the | 1043 client->OnFrameInfo(settings); |
| 1039 // VideoFrame based methods on |client|. | |
| 1040 settings.color = media::PIXEL_FORMAT_I420; | |
| 1041 settings.expected_capture_delay = 0; | |
| 1042 settings.interlaced = false; | |
| 1043 | 1044 |
| 1044 base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds( | 1045 base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds( |
| 1045 1000000.0 / settings.frame_rate + 0.5); | 1046 1000000.0 / frame_rate + 0.5); |
| 1046 | 1047 |
| 1047 client->OnFrameInfo(settings); | |
| 1048 scoped_ptr<VideoCaptureOracle> oracle( | 1048 scoped_ptr<VideoCaptureOracle> oracle( |
| 1049 new VideoCaptureOracle(capture_period, | 1049 new VideoCaptureOracle(capture_period, |
| 1050 kAcceleratedSubscriberIsSupported)); | 1050 kAcceleratedSubscriberIsSupported)); |
| 1051 oracle_proxy_ = new ThreadSafeCaptureOracle(client.Pass(), oracle.Pass()); | 1051 oracle_proxy_ = new ThreadSafeCaptureOracle( |
| 1052 client.Pass(), oracle.Pass(), gfx::Size(width, height)); | |
| 1052 | 1053 |
| 1053 // Allocates the CaptureMachine. The CaptureMachine will be tracking render | 1054 // Allocates the CaptureMachine. The CaptureMachine will be tracking render |
| 1054 // view swapping over its lifetime, and we don't want to lose our reference to | 1055 // view swapping over its lifetime, and we don't want to lose our reference to |
| 1055 // the current render view by starting over with the stale | 1056 // the current render view by starting over with the stale |
| 1056 // |initial_render_view_id_|. | 1057 // |initial_render_view_id_|. |
| 1057 DCHECK(!capture_machine_.get()); | 1058 DCHECK(!capture_machine_.get()); |
| 1058 BrowserThread::PostTaskAndReplyWithResult( | 1059 BrowserThread::PostTaskAndReplyWithResult( |
| 1059 BrowserThread::UI, FROM_HERE, | 1060 BrowserThread::UI, FROM_HERE, |
| 1060 base::Bind(&CaptureMachine::Create, | 1061 base::Bind(&CaptureMachine::Create, |
| 1061 initial_render_process_id_, | 1062 initial_render_process_id_, |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1179 capture_format.height, | 1180 capture_format.height, |
| 1180 capture_format.frame_rate, | 1181 capture_format.frame_rate, |
| 1181 client.Pass()); | 1182 client.Pass()); |
| 1182 } | 1183 } |
| 1183 | 1184 |
| 1184 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 1185 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
| 1185 impl_->StopAndDeAllocate(); | 1186 impl_->StopAndDeAllocate(); |
| 1186 } | 1187 } |
| 1187 | 1188 |
| 1188 } // namespace content | 1189 } // namespace content |
| OLD | NEW |