| 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 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( | 404 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( |
| 405 scoped_ptr<media::VideoCaptureDevice::Client> client, | 405 scoped_ptr<media::VideoCaptureDevice::Client> client, |
| 406 scoped_ptr<VideoCaptureOracle> oracle, | 406 scoped_ptr<VideoCaptureOracle> oracle, |
| 407 const gfx::Size& capture_size, | 407 const gfx::Size& capture_size, |
| 408 int frame_rate) | 408 int frame_rate) |
| 409 : client_(client.Pass()), | 409 : client_(client.Pass()), |
| 410 oracle_(oracle.Pass()), | 410 oracle_(oracle.Pass()), |
| 411 capture_size_(capture_size), | 411 capture_size_(capture_size), |
| 412 frame_rate_(frame_rate) {} | 412 frame_rate_(frame_rate) {} |
| 413 | 413 |
| 414 | |
| 415 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( | 414 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( |
| 416 VideoCaptureOracle::Event event, | 415 VideoCaptureOracle::Event event, |
| 417 base::Time event_time, | 416 base::Time event_time, |
| 418 scoped_refptr<media::VideoFrame>* storage, | 417 scoped_refptr<media::VideoFrame>* storage, |
| 419 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) { | 418 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) { |
| 420 base::AutoLock guard(lock_); | 419 base::AutoLock guard(lock_); |
| 421 | 420 |
| 422 if (!client_) | 421 if (!client_) |
| 423 return false; // Capture is stopped. | 422 return false; // Capture is stopped. |
| 424 | 423 |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 954 // pipeline (see notes at top of this file). It times the start of successive | 953 // pipeline (see notes at top of this file). It times the start of successive |
| 955 // captures and facilitates the processing of each through the stages of the | 954 // captures and facilitates the processing of each through the stages of the |
| 956 // pipeline. | 955 // pipeline. |
| 957 class WebContentsVideoCaptureDevice::Impl : public base::SupportsWeakPtr<Impl> { | 956 class WebContentsVideoCaptureDevice::Impl : public base::SupportsWeakPtr<Impl> { |
| 958 public: | 957 public: |
| 959 | 958 |
| 960 Impl(int render_process_id, int render_view_id); | 959 Impl(int render_process_id, int render_view_id); |
| 961 virtual ~Impl(); | 960 virtual ~Impl(); |
| 962 | 961 |
| 963 // Asynchronous requests to change WebContentsVideoCaptureDevice::Impl state. | 962 // Asynchronous requests to change WebContentsVideoCaptureDevice::Impl state. |
| 964 void AllocateAndStart(int width, | 963 void AllocateAndStart(const media::VideoCaptureParams& params, |
| 965 int height, | |
| 966 int frame_rate, | |
| 967 scoped_ptr<media::VideoCaptureDevice::Client> client); | 964 scoped_ptr<media::VideoCaptureDevice::Client> client); |
| 968 void StopAndDeAllocate(); | 965 void StopAndDeAllocate(); |
| 969 | 966 |
| 970 private: | 967 private: |
| 971 | 968 |
| 972 // Flag indicating current state. | 969 // Flag indicating current state. |
| 973 enum State { | 970 enum State { |
| 974 kIdle, | 971 kIdle, |
| 975 kCapturing, | 972 kCapturing, |
| 976 kError | 973 kError |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 }; | 1015 }; |
| 1019 | 1016 |
| 1020 WebContentsVideoCaptureDevice::Impl::Impl(int render_process_id, | 1017 WebContentsVideoCaptureDevice::Impl::Impl(int render_process_id, |
| 1021 int render_view_id) | 1018 int render_view_id) |
| 1022 : initial_render_process_id_(render_process_id), | 1019 : initial_render_process_id_(render_process_id), |
| 1023 initial_render_view_id_(render_view_id), | 1020 initial_render_view_id_(render_view_id), |
| 1024 state_(kIdle), | 1021 state_(kIdle), |
| 1025 render_thread_("WebContentsVideo_RenderThread") {} | 1022 render_thread_("WebContentsVideo_RenderThread") {} |
| 1026 | 1023 |
| 1027 void WebContentsVideoCaptureDevice::Impl::AllocateAndStart( | 1024 void WebContentsVideoCaptureDevice::Impl::AllocateAndStart( |
| 1028 int width, | 1025 const media::VideoCaptureParams& params, |
| 1029 int height, | |
| 1030 int frame_rate, | |
| 1031 scoped_ptr<VideoCaptureDevice::Client> client) { | 1026 scoped_ptr<VideoCaptureDevice::Client> client) { |
| 1032 DCHECK(thread_checker_.CalledOnValidThread()); | 1027 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1033 | 1028 |
| 1034 if (state_ != kIdle) { | 1029 if (state_ != kIdle) { |
| 1035 DVLOG(1) << "Allocate() invoked when not in state Idle."; | 1030 DVLOG(1) << "Allocate() invoked when not in state Idle."; |
| 1036 return; | 1031 return; |
| 1037 } | 1032 } |
| 1038 | 1033 |
| 1039 if (frame_rate <= 0) { | 1034 if (params.requested_format.frame_rate <= 0) { |
| 1040 DVLOG(1) << "invalid frame_rate: " << frame_rate; | 1035 DVLOG(1) << "invalid frame_rate: " << params.requested_format.frame_rate; |
| 1041 client->OnError(); | 1036 client->OnError(); |
| 1042 return; | 1037 return; |
| 1043 } | 1038 } |
| 1044 | 1039 |
| 1045 if (!render_thread_.Start()) { | 1040 if (!render_thread_.Start()) { |
| 1046 DVLOG(1) << "Failed to spawn render thread."; | 1041 DVLOG(1) << "Failed to spawn render thread."; |
| 1047 client->OnError(); | 1042 client->OnError(); |
| 1048 return; | 1043 return; |
| 1049 } | 1044 } |
| 1050 | 1045 |
| 1051 // Frame dimensions must each be a positive, even integer, since the client | 1046 // Frame dimensions must each be a positive, even integer, since the client |
| 1052 // wants (or will convert to) YUV420. | 1047 // wants (or will convert to) YUV420. |
| 1053 width = MakeEven(width); | 1048 gfx::Size frame_size(MakeEven(params.requested_format.frame_size.width()), |
| 1054 height = MakeEven(height); | 1049 MakeEven(params.requested_format.frame_size.height())); |
| 1055 if (width < kMinFrameWidth || height < kMinFrameHeight) { | 1050 if (frame_size.width() < kMinFrameWidth || |
| 1056 DVLOG(1) << "invalid width (" << width << ") and/or height (" | 1051 frame_size.height() < kMinFrameHeight) { |
| 1057 << height << ")"; | 1052 DVLOG(1) << "invalid frame size: " << frame_size.ToString(); |
| 1058 client->OnError(); | 1053 client->OnError(); |
| 1059 return; | 1054 return; |
| 1060 } | 1055 } |
| 1061 | 1056 |
| 1062 base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds( | 1057 base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds( |
| 1063 1000000.0 / frame_rate + 0.5); | 1058 1000000.0 / params.requested_format.frame_rate + 0.5); |
| 1064 | 1059 |
| 1065 scoped_ptr<VideoCaptureOracle> oracle( | 1060 scoped_ptr<VideoCaptureOracle> oracle( |
| 1066 new VideoCaptureOracle(capture_period, | 1061 new VideoCaptureOracle(capture_period, |
| 1067 kAcceleratedSubscriberIsSupported)); | 1062 kAcceleratedSubscriberIsSupported)); |
| 1068 oracle_proxy_ = new ThreadSafeCaptureOracle( | 1063 oracle_proxy_ = |
| 1069 client.Pass(), oracle.Pass(), gfx::Size(width, height), frame_rate); | 1064 new ThreadSafeCaptureOracle(client.Pass(), |
| 1065 oracle.Pass(), |
| 1066 frame_size, |
| 1067 params.requested_format.frame_rate); |
| 1070 | 1068 |
| 1071 // Allocates the CaptureMachine. The CaptureMachine will be tracking render | 1069 // Allocates the CaptureMachine. The CaptureMachine will be tracking render |
| 1072 // view swapping over its lifetime, and we don't want to lose our reference to | 1070 // view swapping over its lifetime, and we don't want to lose our reference to |
| 1073 // the current render view by starting over with the stale | 1071 // the current render view by starting over with the stale |
| 1074 // |initial_render_view_id_|. | 1072 // |initial_render_view_id_|. |
| 1075 DCHECK(!capture_machine_.get()); | 1073 DCHECK(!capture_machine_.get()); |
| 1076 BrowserThread::PostTaskAndReplyWithResult( | 1074 BrowserThread::PostTaskAndReplyWithResult( |
| 1077 BrowserThread::UI, FROM_HERE, | 1075 BrowserThread::UI, FROM_HERE, |
| 1078 base::Bind(&CaptureMachine::Create, | 1076 base::Bind(&CaptureMachine::Create, |
| 1079 initial_render_process_id_, | 1077 initial_render_process_id_, |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 int render_view_id = -1; | 1180 int render_view_id = -1; |
| 1183 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( | 1181 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( |
| 1184 device_id, &render_process_id, &render_view_id)) { | 1182 device_id, &render_process_id, &render_view_id)) { |
| 1185 return NULL; | 1183 return NULL; |
| 1186 } | 1184 } |
| 1187 | 1185 |
| 1188 return new WebContentsVideoCaptureDevice(render_process_id, render_view_id); | 1186 return new WebContentsVideoCaptureDevice(render_process_id, render_view_id); |
| 1189 } | 1187 } |
| 1190 | 1188 |
| 1191 void WebContentsVideoCaptureDevice::AllocateAndStart( | 1189 void WebContentsVideoCaptureDevice::AllocateAndStart( |
| 1192 const media::VideoCaptureCapability& capture_format, | 1190 const media::VideoCaptureParams& params, |
| 1193 scoped_ptr<Client> client) { | 1191 scoped_ptr<Client> client) { |
| 1194 DVLOG(1) << "Allocating " << capture_format.width << "x" | 1192 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
| 1195 << capture_format.height; | 1193 impl_->AllocateAndStart(params, client.Pass()); |
| 1196 impl_->AllocateAndStart(capture_format.width, | |
| 1197 capture_format.height, | |
| 1198 capture_format.frame_rate, | |
| 1199 client.Pass()); | |
| 1200 } | 1194 } |
| 1201 | 1195 |
| 1202 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 1196 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
| 1203 impl_->StopAndDeAllocate(); | 1197 impl_->StopAndDeAllocate(); |
| 1204 } | 1198 } |
| 1205 | 1199 |
| 1206 } // namespace content | 1200 } // namespace content |
| OLD | NEW |