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 |