Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: content/browser/renderer_host/media/web_contents_video_capture_device.cc

Issue 11339014: Move content\browser\renderer_host\media to content namespace. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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. Therefore, the process of capturing has been split up into a 7 // performance. Therefore, the process of capturing has been split up into a
8 // pipeline of three stages. Each stage executes on its own thread: 8 // pipeline of three stages. Each stage executes on its own thread:
9 // 9 //
10 // 1. Capture: A bitmap is snapshotted/copied from the RenderView's backing 10 // 1. Capture: A bitmap is snapshotted/copied from the RenderView's backing
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 } 135 }
136 // Make each dimension a positive, even number; if not already. 136 // Make each dimension a positive, even number; if not already.
137 fitted_width = std::max(kMinFrameWidth, MakeEven(fitted_width)); 137 fitted_width = std::max(kMinFrameWidth, MakeEven(fitted_width));
138 fitted_height = std::max(kMinFrameHeight, MakeEven(fitted_height)); 138 fitted_height = std::max(kMinFrameHeight, MakeEven(fitted_height));
139 139
140 *fitted_size = gfx::Size(fitted_width, fitted_height); 140 *fitted_size = gfx::Size(fitted_width, fitted_height);
141 } 141 }
142 142
143 // Keeps track of the RenderView to be sourced, and executes copying of the 143 // Keeps track of the RenderView to be sourced, and executes copying of the
144 // backing store on the UI BrowserThread. 144 // backing store on the UI BrowserThread.
145 class BackingStoreCopier : public content::WebContentsObserver { 145 class BackingStoreCopier : public WebContentsObserver {
146 public: 146 public:
147 // Result status and done callback used with StartCopy(). 147 // Result status and done callback used with StartCopy().
148 enum Result { 148 enum Result {
149 OK, 149 OK,
150 TRANSIENT_ERROR, 150 TRANSIENT_ERROR,
151 NO_SOURCE, 151 NO_SOURCE,
152 }; 152 };
153 typedef base::Callback<void(Result result, 153 typedef base::Callback<void(Result result,
154 scoped_ptr<skia::PlatformBitmap> capture, 154 scoped_ptr<skia::PlatformBitmap> capture,
155 const base::Time& capture_time)> DoneCB; 155 const base::Time& capture_time)> DoneCB;
156 156
157 BackingStoreCopier(int render_process_id, int render_view_id); 157 BackingStoreCopier(int render_process_id, int render_view_id);
158 158
159 // If non-NULL, use the given |override| to access the backing store. 159 // If non-NULL, use the given |override| to access the backing store.
160 // This is used for unit testing. 160 // This is used for unit testing.
161 void SetRenderWidgetHostForTesting(content::RenderWidgetHost* override); 161 void SetRenderWidgetHostForTesting(RenderWidgetHost* override);
162 162
163 // Starts the copy from the backing store. Must be run on the UI 163 // Starts the copy from the backing store. Must be run on the UI
164 // BrowserThread. |done_cb| is invoked with result status. When successful 164 // BrowserThread. |done_cb| is invoked with result status. When successful
165 // (OK), the bitmap of the capture is transferred to the callback along with 165 // (OK), the bitmap of the capture is transferred to the callback along with
166 // the timestamp at which the capture was completed. 166 // the timestamp at which the capture was completed.
167 void StartCopy(int desired_width, int desired_height, const DoneCB& done_cb); 167 void StartCopy(int desired_width, int desired_height, const DoneCB& done_cb);
168 168
169 private: 169 private:
170 void LookUpAndObserveWebContents(); 170 void LookUpAndObserveWebContents();
171 171
172 void CopyFromBackingStoreComplete(scoped_ptr<skia::PlatformBitmap> capture, 172 void CopyFromBackingStoreComplete(scoped_ptr<skia::PlatformBitmap> capture,
173 const DoneCB& done_cb, bool success); 173 const DoneCB& done_cb, bool success);
174 174
175 // The "starting point" to find the capture source. 175 // The "starting point" to find the capture source.
176 const int render_process_id_; 176 const int render_process_id_;
177 const int render_view_id_; 177 const int render_view_id_;
178 178
179 // If the following is NULL (normal behavior), the implementation should 179 // If the following is NULL (normal behavior), the implementation should
180 // access RenderWidgetHost via web_contents(). 180 // access RenderWidgetHost via web_contents().
181 content::RenderWidgetHost* rwh_for_testing_; 181 RenderWidgetHost* rwh_for_testing_;
182 182
183 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier); 183 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier);
184 }; 184 };
185 185
186 // Renders captures (from the backing store) into video frame buffers on a 186 // Renders captures (from the backing store) into video frame buffers on a
187 // separate thread. Manages use of internally-owned video frame buffers. 187 // separate thread. Manages use of internally-owned video frame buffers.
188 class VideoFrameRenderer { 188 class VideoFrameRenderer {
189 public: 189 public:
190 typedef base::Callback<void(const SkBitmap*)> DoneCB; 190 typedef base::Callback<void(const SkBitmap*)> DoneCB;
191 191
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 263
264 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); 264 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer);
265 }; 265 };
266 266
267 BackingStoreCopier::BackingStoreCopier(int render_process_id, 267 BackingStoreCopier::BackingStoreCopier(int render_process_id,
268 int render_view_id) 268 int render_view_id)
269 : render_process_id_(render_process_id), render_view_id_(render_view_id), 269 : render_process_id_(render_process_id), render_view_id_(render_view_id),
270 rwh_for_testing_(NULL) {} 270 rwh_for_testing_(NULL) {}
271 271
272 void BackingStoreCopier::LookUpAndObserveWebContents() { 272 void BackingStoreCopier::LookUpAndObserveWebContents() {
273 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
274 274
275 // Look-up the RenderViewHost and, from that, the WebContents that wraps it. 275 // Look-up the RenderViewHost and, from that, the WebContents that wraps it.
276 // If successful, begin observing the WebContents instance. If unsuccessful, 276 // If successful, begin observing the WebContents instance. If unsuccessful,
277 // stop observing and post an error. 277 // stop observing and post an error.
278 // 278 //
279 // Why this can be unsuccessful: The request for mirroring originates in a 279 // Why this can be unsuccessful: The request for mirroring originates in a
280 // render process, and this request is based on the current RenderView 280 // render process, and this request is based on the current RenderView
281 // associated with a tab. However, by the time we get up-and-running here, 281 // associated with a tab. However, by the time we get up-and-running here,
282 // there have been multiple back-and-forth IPCs between processes, as well as 282 // there have been multiple back-and-forth IPCs between processes, as well as
283 // a bit of indirection across threads. It's easily possible that, in the 283 // a bit of indirection across threads. It's easily possible that, in the
284 // meantime, the original RenderView may have gone away. 284 // meantime, the original RenderView may have gone away.
285 content::RenderViewHost* const rvh = 285 RenderViewHost* const rvh =
286 content::RenderViewHost::FromID(render_process_id_, render_view_id_); 286 RenderViewHost::FromID(render_process_id_, render_view_id_);
287 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" 287 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID("
288 << render_process_id_ << ", " << render_view_id_ 288 << render_process_id_ << ", " << render_view_id_
289 << ") returned NULL."; 289 << ") returned NULL.";
290 Observe(rvh ? content::WebContents::FromRenderViewHost(rvh) : NULL); 290 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
291 DVLOG_IF(1, !web_contents()) 291 DVLOG_IF(1, !web_contents())
292 << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; 292 << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL.";
293 } 293 }
294 294
295 void BackingStoreCopier::SetRenderWidgetHostForTesting( 295 void BackingStoreCopier::SetRenderWidgetHostForTesting(
296 content::RenderWidgetHost* override) { 296 RenderWidgetHost* override) {
297 rwh_for_testing_ = override; 297 rwh_for_testing_ = override;
298 } 298 }
299 299
300 void BackingStoreCopier::StartCopy(int desired_width, int desired_height, 300 void BackingStoreCopier::StartCopy(int desired_width, int desired_height,
301 const DoneCB& done_cb) { 301 const DoneCB& done_cb) {
302 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
303 303
304 TRACE_EVENT_ASYNC_BEGIN0("mirroring", "Capture", this); 304 TRACE_EVENT_ASYNC_BEGIN0("mirroring", "Capture", this);
305 305
306 content::RenderWidgetHost* rwh; 306 RenderWidgetHost* rwh;
307 if (rwh_for_testing_) { 307 if (rwh_for_testing_) {
308 rwh = rwh_for_testing_; 308 rwh = rwh_for_testing_;
309 } else { 309 } else {
310 if (!web_contents()) { // No source yet. 310 if (!web_contents()) { // No source yet.
311 LookUpAndObserveWebContents(); 311 LookUpAndObserveWebContents();
312 if (!web_contents()) { // No source ever. 312 if (!web_contents()) { // No source ever.
313 done_cb.Run(NO_SOURCE, 313 done_cb.Run(NO_SOURCE,
314 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); 314 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time());
315 return; 315 return;
316 } 316 }
317 } 317 }
318 rwh = web_contents()->GetRenderViewHost(); 318 rwh = web_contents()->GetRenderViewHost();
319 if (!rwh) { 319 if (!rwh) {
320 // Transient failure state (e.g., a RenderView is being replaced). 320 // Transient failure state (e.g., a RenderView is being replaced).
321 done_cb.Run(TRANSIENT_ERROR, 321 done_cb.Run(TRANSIENT_ERROR,
322 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); 322 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time());
323 return; 323 return;
324 } 324 }
325 } 325 }
326 326
327 gfx::Size fitted_size; 327 gfx::Size fitted_size;
328 if (content::RenderWidgetHostView* const view = rwh->GetView()) { 328 if (RenderWidgetHostView* const view = rwh->GetView()) {
329 const gfx::Size& view_size = view->GetViewBounds().size(); 329 const gfx::Size& view_size = view->GetViewBounds().size();
330 if (!view_size.IsEmpty()) { 330 if (!view_size.IsEmpty()) {
331 CalculateFittedSize(view_size.width(), view_size.height(), 331 CalculateFittedSize(view_size.width(), view_size.height(),
332 desired_width, desired_height, 332 desired_width, desired_height,
333 &fitted_size); 333 &fitted_size);
334 } 334 }
335 } 335 }
336 336
337 // TODO(miu): Look into tweaking the interface to CopyFromBackingStore, since 337 // TODO(miu): Look into tweaking the interface to CopyFromBackingStore, since
338 // it seems poor to have to allocate a new skia::PlatformBitmap as an output 338 // it seems poor to have to allocate a new skia::PlatformBitmap as an output
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 // 600 //
601 // CaptureMachine manages a simple state machine and the pipeline (see notes at 601 // CaptureMachine manages a simple state machine and the pipeline (see notes at
602 // top of this file). It times the start of successive captures and 602 // top of this file). It times the start of successive captures and
603 // facilitates the processing of each through the stages of the pipeline. 603 // facilitates the processing of each through the stages of the pipeline.
604 class CaptureMachine 604 class CaptureMachine
605 : public base::RefCountedThreadSafe<CaptureMachine, CaptureMachine> { 605 : public base::RefCountedThreadSafe<CaptureMachine, CaptureMachine> {
606 public: 606 public:
607 CaptureMachine(int render_process_id, int render_view_id); 607 CaptureMachine(int render_process_id, int render_view_id);
608 608
609 // Set capture source to the given |override| for unit testing. 609 // Set capture source to the given |override| for unit testing.
610 void SetRenderWidgetHostForTesting(content::RenderWidgetHost* override); 610 void SetRenderWidgetHostForTesting(RenderWidgetHost* override);
611 611
612 // Synchronously sets/unsets the consumer. Pass |consumer| as NULL to remove 612 // Synchronously sets/unsets the consumer. Pass |consumer| as NULL to remove
613 // the reference to the consumer; then, once this method returns, 613 // the reference to the consumer; then, once this method returns,
614 // CaptureMachine will no longer invoke callbacks on the old consumer from any 614 // CaptureMachine will no longer invoke callbacks on the old consumer from any
615 // thread. 615 // thread.
616 void SetConsumer(media::VideoCaptureDevice::EventHandler* consumer); 616 void SetConsumer(media::VideoCaptureDevice::EventHandler* consumer);
617 617
618 // Asynchronous requests to change CaptureMachine state. 618 // Asynchronous requests to change CaptureMachine state.
619 void Allocate(int width, int height, int frame_rate); 619 void Allocate(int width, int height, int frame_rate);
620 void Start(); 620 void Start();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 : manager_thread_("WebContentsVideo_ManagerThread"), 685 : manager_thread_("WebContentsVideo_ManagerThread"),
686 state_(kIdle), 686 state_(kIdle),
687 is_snapshotting_(false), 687 is_snapshotting_(false),
688 num_renders_pending_(0), 688 num_renders_pending_(0),
689 copier_(render_process_id, render_view_id), 689 copier_(render_process_id, render_view_id),
690 deliverer_(&consumer_) { 690 deliverer_(&consumer_) {
691 manager_thread_.Start(); 691 manager_thread_.Start();
692 } 692 }
693 693
694 void CaptureMachine::SetRenderWidgetHostForTesting( 694 void CaptureMachine::SetRenderWidgetHostForTesting(
695 content::RenderWidgetHost* override) { 695 RenderWidgetHost* override) {
696 copier_.SetRenderWidgetHostForTesting(override); 696 copier_.SetRenderWidgetHostForTesting(override);
697 } 697 }
698 698
699 void CaptureMachine::SetConsumer( 699 void CaptureMachine::SetConsumer(
700 media::VideoCaptureDevice::EventHandler* consumer) { 700 media::VideoCaptureDevice::EventHandler* consumer) {
701 consumer_.SetConsumer(consumer); 701 consumer_.SetConsumer(consumer);
702 } 702 }
703 703
704 void CaptureMachine::Allocate(int width, int height, int frame_rate) { 704 void CaptureMachine::Allocate(int width, int height, int frame_rate) {
705 ENSURE_INVOKED_ON_THREAD(manager_thread_, 705 ENSURE_INVOKED_ON_THREAD(manager_thread_,
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 // point (because CaptureMachine's ref-count is zero). 793 // point (because CaptureMachine's ref-count is zero).
794 } 794 }
795 795
796 // static 796 // static
797 void CaptureMachine::Destruct(const CaptureMachine* x) { 797 void CaptureMachine::Destruct(const CaptureMachine* x) {
798 // The current thread is very likely to be one owned by CaptureMachine. When 798 // The current thread is very likely to be one owned by CaptureMachine. When
799 // ~CaptureMachine() is called, it will attempt to join with the 799 // ~CaptureMachine() is called, it will attempt to join with the
800 // CaptureMachine-owned threads, including itself. Since it's illegal for a 800 // CaptureMachine-owned threads, including itself. Since it's illegal for a
801 // thread to join with itself, we need to trampoline the destructor call to 801 // thread to join with itself, we need to trampoline the destructor call to
802 // another thread. 802 // another thread.
803 content::BrowserThread::PostBlockingPoolTask( 803 BrowserThread::PostBlockingPoolTask(
804 FROM_HERE, base::Bind(&DeleteFromOutsideThread, x)); 804 FROM_HERE, base::Bind(&DeleteFromOutsideThread, x));
805 } 805 }
806 806
807 // static 807 // static
808 void CaptureMachine::DeleteFromOutsideThread(const CaptureMachine* x) { 808 void CaptureMachine::DeleteFromOutsideThread(const CaptureMachine* x) {
809 // Note: Thread joins are about to happen here (in ~CaptureThread()). 809 // Note: Thread joins are about to happen here (in ~CaptureThread()).
810 delete x; 810 delete x;
811 } 811 }
812 812
813 void CaptureMachine::TransitionStateTo(State next_state) { 813 void CaptureMachine::TransitionStateTo(State next_state) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 if (!is_snapshotting_) { 866 if (!is_snapshotting_) {
867 is_snapshotting_ = true; 867 is_snapshotting_ = true;
868 868
869 const BackingStoreCopier::DoneCB& done_cb = 869 const BackingStoreCopier::DoneCB& done_cb =
870 media::BindToLoop(manager_thread_.message_loop_proxy(), 870 media::BindToLoop(manager_thread_.message_loop_proxy(),
871 base::Bind(&CaptureMachine::SnapshotComplete, this)); 871 base::Bind(&CaptureMachine::SnapshotComplete, this));
872 const base::Closure& start_cb = 872 const base::Closure& start_cb =
873 base::Bind(&BackingStoreCopier::StartCopy, 873 base::Bind(&BackingStoreCopier::StartCopy,
874 base::Unretained(&copier_), 874 base::Unretained(&copier_),
875 settings_.width, settings_.height, done_cb); 875 settings_.width, settings_.height, done_cb);
876 content::BrowserThread::PostTask( 876 BrowserThread::PostTask(
877 content::BrowserThread::UI, FROM_HERE, start_cb); 877 BrowserThread::UI, FROM_HERE, start_cb);
878 } 878 }
879 879
880 ScheduleNextFrameCapture(); 880 ScheduleNextFrameCapture();
881 } 881 }
882 882
883 void CaptureMachine::SnapshotComplete(BackingStoreCopier::Result result, 883 void CaptureMachine::SnapshotComplete(BackingStoreCopier::Result result,
884 scoped_ptr<skia::PlatformBitmap> capture, 884 scoped_ptr<skia::PlatformBitmap> capture,
885 const base::Time& capture_time) { 885 const base::Time& capture_time) {
886 DCHECK_EQ(manager_thread_.message_loop(), MessageLoop::current()); 886 DCHECK_EQ(manager_thread_.message_loop(), MessageLoop::current());
887 887
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 renderer_.Release(frame_buffer); 940 renderer_.Release(frame_buffer);
941 } 941 }
942 942
943 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( 943 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
944 const media::VideoCaptureDevice::Name& name, 944 const media::VideoCaptureDevice::Name& name,
945 int render_process_id, int render_view_id) 945 int render_process_id, int render_view_id)
946 : device_name_(name), 946 : device_name_(name),
947 capturer_(new CaptureMachine(render_process_id, render_view_id)) {} 947 capturer_(new CaptureMachine(render_process_id, render_view_id)) {}
948 948
949 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( 949 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
950 content::RenderWidgetHost* test_source) 950 RenderWidgetHost* test_source)
951 : capturer_(new CaptureMachine(-1, -1)) { 951 : capturer_(new CaptureMachine(-1, -1)) {
952 device_name_.device_name = "WebContentsForTesting"; 952 device_name_.device_name = "WebContentsForTesting";
953 device_name_.unique_id = "-1:-1"; 953 device_name_.unique_id = "-1:-1";
954 capturer_->SetRenderWidgetHostForTesting(test_source); 954 capturer_->SetRenderWidgetHostForTesting(test_source);
955 } 955 }
956 956
957 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { 957 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
958 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; 958 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
959 } 959 }
960 960
(...skipping 20 matching lines...) Expand all
981 "WebContents[%.*s]", 981 "WebContents[%.*s]",
982 static_cast<int>(device_id.size()), device_id.data()); 982 static_cast<int>(device_id.size()), device_id.data());
983 name.unique_id = device_id; 983 name.unique_id = device_id;
984 984
985 return new WebContentsVideoCaptureDevice( 985 return new WebContentsVideoCaptureDevice(
986 name, render_process_id, render_view_id); 986 name, render_process_id, render_view_id);
987 } 987 }
988 988
989 // static 989 // static
990 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::CreateForTesting( 990 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::CreateForTesting(
991 content::RenderWidgetHost* test_source) { 991 RenderWidgetHost* test_source) {
992 return new WebContentsVideoCaptureDevice(test_source); 992 return new WebContentsVideoCaptureDevice(test_source);
993 } 993 }
994 994
995 void WebContentsVideoCaptureDevice::Allocate( 995 void WebContentsVideoCaptureDevice::Allocate(
996 int width, int height, int frame_rate, 996 int width, int height, int frame_rate,
997 VideoCaptureDevice::EventHandler* consumer) { 997 VideoCaptureDevice::EventHandler* consumer) {
998 DCHECK(capturer_); 998 DCHECK(capturer_);
999 capturer_->SetConsumer(consumer); 999 capturer_->SetConsumer(consumer);
1000 capturer_->Allocate(width, height, frame_rate); 1000 capturer_->Allocate(width, height, frame_rate);
1001 } 1001 }
(...skipping 13 matching lines...) Expand all
1015 capturer_->SetConsumer(NULL); 1015 capturer_->SetConsumer(NULL);
1016 capturer_->DeAllocate(); 1016 capturer_->DeAllocate();
1017 } 1017 }
1018 1018
1019 const media::VideoCaptureDevice::Name& 1019 const media::VideoCaptureDevice::Name&
1020 WebContentsVideoCaptureDevice::device_name() { 1020 WebContentsVideoCaptureDevice::device_name() {
1021 return device_name_; 1021 return device_name_;
1022 } 1022 }
1023 1023
1024 } // namespace content 1024 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698