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

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

Issue 48113011: Remove media::VideoFrame from media::VideoCaptureDevice::Client interface (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@git-svn
Patch Set: 5b80a5e9 scoped_refptr-ization. Created 7 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
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
3 // found in the LICENSE file. 2 // found in the LICENSE file.
4 3
5 #include "content/browser/renderer_host/media/video_capture_controller.h" 4 #include "content/browser/renderer_host/media/video_capture_controller.h"
6 5
7 #include <set> 6 #include <set>
8 7
9 #include "base/bind.h" 8 #include "base/bind.h"
10 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/stl_util.h" 10 #include "base/stl_util.h"
13 #include "content/browser/renderer_host/media/media_stream_manager.h" 11 #include "content/browser/renderer_host/media/media_stream_manager.h"
14 #include "content/browser/renderer_host/media/video_capture_manager.h" 12 #include "content/browser/renderer_host/media/video_capture_manager.h"
15 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
16 #include "media/base/video_frame.h" 14 #include "media/base/video_frame.h"
17 #include "media/base/video_util.h" 15 #include "media/base/video_util.h"
18 #include "media/base/yuv_convert.h" 16 #include "media/base/yuv_convert.h"
19 17
20 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) 18 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
21 #include "third_party/libyuv/include/libyuv.h" 19 #include "third_party/libyuv/include/libyuv.h"
22 #endif 20 #endif
23 21
24 namespace content { 22 namespace content {
25 23
24 namespace {
25
26 // The number of buffers that VideoCaptureBufferPool should allocate. 26 // The number of buffers that VideoCaptureBufferPool should allocate.
27 static const int kNoOfBuffers = 3; 27 const int kNoOfBuffers = 3;
28
29 class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer {
30 public:
31 PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool,
32 int buffer_id,
33 void* data,
34 size_t size)
35 : Buffer(data, size), pool_(pool), buffer_id_(buffer_id) {}
36
37 private:
38 virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(buffer_id_); }
39
40 const scoped_refptr<VideoCaptureBufferPool> pool_;
41 const int buffer_id_;
42 };
43
44 } // anonymous namespace
28 45
29 struct VideoCaptureController::ControllerClient { 46 struct VideoCaptureController::ControllerClient {
30 ControllerClient( 47 ControllerClient(
31 const VideoCaptureControllerID& id, 48 const VideoCaptureControllerID& id,
32 VideoCaptureControllerEventHandler* handler, 49 VideoCaptureControllerEventHandler* handler,
33 base::ProcessHandle render_process, 50 base::ProcessHandle render_process,
34 const media::VideoCaptureParams& params) 51 const media::VideoCaptureParams& params)
35 : controller_id(id), 52 : controller_id(id),
36 event_handler(handler), 53 event_handler(handler),
37 render_process_handle(render_process), 54 render_process_handle(render_process),
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 // v4l2_thread on Linux, and the UI thread for tab capture. 95 // v4l2_thread on Linux, and the UI thread for tab capture.
79 class VideoCaptureController::VideoCaptureDeviceClient 96 class VideoCaptureController::VideoCaptureDeviceClient
80 : public media::VideoCaptureDevice::Client { 97 : public media::VideoCaptureDevice::Client {
81 public: 98 public:
82 explicit VideoCaptureDeviceClient( 99 explicit VideoCaptureDeviceClient(
83 const base::WeakPtr<VideoCaptureController>& controller, 100 const base::WeakPtr<VideoCaptureController>& controller,
84 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool); 101 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
85 virtual ~VideoCaptureDeviceClient(); 102 virtual ~VideoCaptureDeviceClient();
86 103
87 // VideoCaptureDevice::Client implementation. 104 // VideoCaptureDevice::Client implementation.
88 virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer( 105 virtual scoped_refptr<Buffer> ReserveOutputBuffer(
106 media::VideoFrame::Format format,
89 const gfx::Size& size) OVERRIDE; 107 const gfx::Size& size) OVERRIDE;
90 virtual void OnIncomingCapturedFrame(const uint8* data, 108 virtual void OnIncomingCapturedFrame(const uint8* data,
91 int length, 109 int length,
92 base::Time timestamp, 110 base::Time timestamp,
93 int rotation, 111 int rotation,
94 bool flip_vert, 112 bool flip_vert,
95 bool flip_horiz) OVERRIDE; 113 bool flip_horiz) OVERRIDE;
96 virtual void OnIncomingCapturedVideoFrame( 114 virtual void OnIncomingCapturedBuffer(const scoped_refptr<Buffer>& buffer,
97 const scoped_refptr<media::VideoFrame>& frame, 115 media::VideoFrame::Format format,
98 base::Time timestamp) OVERRIDE; 116 const gfx::Size& dimensions,
117 base::Time timestamp) OVERRIDE;
99 virtual void OnError() OVERRIDE; 118 virtual void OnError() OVERRIDE;
100 virtual void OnFrameInfo( 119 virtual void OnFrameInfo(
101 const media::VideoCaptureCapability& info) OVERRIDE; 120 const media::VideoCaptureCapability& info) OVERRIDE;
102 virtual void OnFrameInfoChanged( 121 virtual void OnFrameInfoChanged(
103 const media::VideoCaptureCapability& info) OVERRIDE; 122 const media::VideoCaptureCapability& info) OVERRIDE;
104 123
105 private: 124 private:
106 scoped_refptr<media::VideoFrame> DoReserveI420VideoFrame( 125 scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format,
107 const gfx::Size& size, 126 const gfx::Size& dimensions,
108 int rotation); 127 int rotation);
109 128
110 // The controller to which we post events. 129 // The controller to which we post events.
111 const base::WeakPtr<VideoCaptureController> controller_; 130 const base::WeakPtr<VideoCaptureController> controller_;
112 131
113 // The pool of shared-memory buffers used for capturing. 132 // The pool of shared-memory buffers used for capturing.
114 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; 133 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
115 134
135 // The set of buffers that have been used for rotated capturing.
136 std::set<int> rotated_buffers_;
jiayl 2013/11/08 22:16:46 I don't find where this is used. Plus don't we nee
sheu 2013/11/09 00:59:30 It's used in DoReserveOutputBuffers. See the comm
137
116 // Chopped pixels in width/height in case video capture device has odd 138 // Chopped pixels in width/height in case video capture device has odd
117 // numbers for width/height. 139 // numbers for width/height.
118 int chopped_width_; 140 int chopped_width_;
119 int chopped_height_; 141 int chopped_height_;
120 142
121 // Tracks the current frame format. 143 // Tracks the current frame format.
122 media::VideoCaptureCapability frame_info_; 144 media::VideoCaptureCapability frame_info_;
123 }; 145 };
124 146
125 VideoCaptureController::VideoCaptureController() 147 VideoCaptureController::VideoCaptureController()
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 // If this buffer is not held by this client, or this client doesn't exist 253 // If this buffer is not held by this client, or this client doesn't exist
232 // in controller, do nothing. 254 // in controller, do nothing.
233 if (!client || !client->active_buffers.erase(buffer_id)) { 255 if (!client || !client->active_buffers.erase(buffer_id)) {
234 NOTREACHED(); 256 NOTREACHED();
235 return; 257 return;
236 } 258 }
237 259
238 buffer_pool_->RelinquishConsumerHold(buffer_id, 1); 260 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
239 } 261 }
240 262
241 scoped_refptr<media::VideoFrame> 263 scoped_refptr<media::VideoCaptureDevice::Client::Buffer>
242 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer( 264 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer(
265 media::VideoFrame::Format format,
243 const gfx::Size& size) { 266 const gfx::Size& size) {
244 return DoReserveI420VideoFrame(size, 0); 267 return DoReserveOutputBuffer(format, size, 0);
245 } 268 }
246 269
247 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( 270 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
248 const uint8* data, 271 const uint8* data,
249 int length, 272 int length,
250 base::Time timestamp, 273 base::Time timestamp,
251 int rotation, 274 int rotation,
252 bool flip_vert, 275 bool flip_vert,
253 bool flip_horiz) { 276 bool flip_horiz) {
254 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); 277 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
255 278
256 if (!frame_info_.IsValid()) 279 if (!frame_info_.IsValid())
257 return; 280 return;
258 281
259 scoped_refptr<media::VideoFrame> dst = DoReserveI420VideoFrame( 282 const gfx::Size dimensions(frame_info_.width, frame_info_.height);
260 gfx::Size(frame_info_.width, frame_info_.height), rotation); 283 scoped_refptr<Buffer> buffer =
284 DoReserveOutputBuffer(media::VideoFrame::I420, dimensions, rotation);
261 285
262 if (!dst.get()) 286 if (!buffer)
263 return; 287 return;
264 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) 288 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
265 289 uint8* yplane = reinterpret_cast<uint8*>(buffer->data());
266 uint8* yplane = dst->data(media::VideoFrame::kYPlane); 290 uint8* uplane =
267 uint8* uplane = dst->data(media::VideoFrame::kUPlane); 291 yplane +
268 uint8* vplane = dst->data(media::VideoFrame::kVPlane); 292 media::VideoFrame::PlaneAllocationSize(
293 media::VideoFrame::I420, media::VideoFrame::kYPlane, dimensions);
294 uint8* vplane =
295 uplane +
296 media::VideoFrame::PlaneAllocationSize(
297 media::VideoFrame::I420, media::VideoFrame::kUPlane, dimensions);
269 int yplane_stride = frame_info_.width; 298 int yplane_stride = frame_info_.width;
270 int uv_plane_stride = (frame_info_.width + 1) / 2; 299 int uv_plane_stride = (frame_info_.width + 1) / 2;
271 int crop_x = 0; 300 int crop_x = 0;
272 int crop_y = 0; 301 int crop_y = 0;
273 int destination_width = frame_info_.width; 302 int destination_width = frame_info_.width;
274 int destination_height = frame_info_.height; 303 int destination_height = frame_info_.height;
275 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; 304 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY;
276 // Assuming rotation happens first and flips next, we can consolidate both 305 // Assuming rotation happens first and flips next, we can consolidate both
277 // vertical and horizontal flips together with rotation into two variables: 306 // vertical and horizontal flips together with rotation into two variables:
278 // new_rotation = (rotation + 180 * vertical_flip) modulo 360 307 // new_rotation = (rotation + 180 * vertical_flip) modulo 360
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 } 410 }
382 #else 411 #else
383 // Libyuv is not linked in for Android WebView builds, but video capture is 412 // Libyuv is not linked in for Android WebView builds, but video capture is
384 // not used in those builds either. Whenever libyuv is added in that build, 413 // not used in those builds either. Whenever libyuv is added in that build,
385 // address all these #ifdef parts, see http://crbug.com/299611 . 414 // address all these #ifdef parts, see http://crbug.com/299611 .
386 NOTREACHED(); 415 NOTREACHED();
387 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) 416 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
388 BrowserThread::PostTask( 417 BrowserThread::PostTask(
389 BrowserThread::IO, 418 BrowserThread::IO,
390 FROM_HERE, 419 FROM_HERE,
391 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 420 base::Bind(
392 controller_, 421 &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread,
393 dst, 422 controller_,
394 frame_info_.frame_rate, 423 buffer,
395 timestamp)); 424 dimensions,
425 frame_info_.frame_rate,
426 timestamp));
396 } 427 }
397 428
398 void 429 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
399 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( 430 const scoped_refptr<Buffer>& buffer,
400 const scoped_refptr<media::VideoFrame>& frame, 431 media::VideoFrame::Format format,
432 const gfx::Size& dimensions,
401 base::Time timestamp) { 433 base::Time timestamp) {
434 // The capture pipeline expects I420 for now.
435 DCHECK_EQ(format, media::VideoFrame::I420)
436 << "Non-I420 output buffer returned";
437 DCHECK_NE(buffer_pool_->RecognizeReservedBuffer(buffer->data()),
438 VideoCaptureBufferPool::kInvalidId)
439 << "Non-reserved buffer returned";
402 440
403 // If this is a frame that belongs to the buffer pool, we can forward it 441 BrowserThread::PostTask(
404 // directly to the IO thread and be done. 442 BrowserThread::IO,
405 if (buffer_pool_->RecognizeReservedBuffer( 443 FROM_HERE,
406 frame->shared_memory_handle()) >= 0) { 444 base::Bind(
407 BrowserThread::PostTask(BrowserThread::IO, 445 &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread,
408 FROM_HERE, 446 controller_,
409 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 447 buffer,
410 controller_, frame, frame_info_.frame_rate, timestamp)); 448 dimensions,
411 return; 449 frame_info_.frame_rate,
412 } 450 timestamp));
413
414 NOTREACHED() << "Frames should always belong to the buffer pool.";
415 } 451 }
416 452
417 void VideoCaptureController::VideoCaptureDeviceClient::OnError() { 453 void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
418 BrowserThread::PostTask(BrowserThread::IO, 454 BrowserThread::PostTask(BrowserThread::IO,
419 FROM_HERE, 455 FROM_HERE,
420 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); 456 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
421 } 457 }
422 458
423 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo( 459 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
424 const media::VideoCaptureCapability& info) { 460 const media::VideoCaptureCapability& info) {
(...skipping 11 matching lines...) Expand all
436 } else { 472 } else {
437 chopped_height_ = 0; 473 chopped_height_ = 0;
438 } 474 }
439 } 475 }
440 476
441 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged( 477 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
442 const media::VideoCaptureCapability& info) { 478 const media::VideoCaptureCapability& info) {
443 OnFrameInfo(info); 479 OnFrameInfo(info);
444 } 480 }
445 481
446 scoped_refptr<media::VideoFrame> 482 scoped_refptr<media::VideoCaptureDevice::Client::Buffer>
447 VideoCaptureController::VideoCaptureDeviceClient::DoReserveI420VideoFrame( 483 VideoCaptureController::VideoCaptureDeviceClient::DoReserveOutputBuffer(
448 const gfx::Size& size, 484 media::VideoFrame::Format format,
485 const gfx::Size& dimensions,
449 int rotation) { 486 int rotation) {
487 // The capture pipeline expects I420 for now.
488 DCHECK_EQ(format, media::VideoFrame::I420)
489 << "Non-I420 output buffer requested";
490
450 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; 491 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
451 scoped_refptr<media::VideoFrame> frame = 492 const size_t frame_bytes =
452 buffer_pool_->ReserveI420VideoFrame(size, rotation, &buffer_id_to_drop); 493 media::VideoFrame::AllocationSize(format, dimensions);
494
495 int buffer_id =
496 buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop);
497 if (buffer_id == VideoCaptureBufferPool::kInvalidId)
498 return NULL;
499 void* data;
500 size_t size;
501 buffer_pool_->GetBufferInfo(buffer_id, &data, &size);
502
503 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer(
504 new PoolBuffer(buffer_pool_, buffer_id, data, size));
505 buffer_id = VideoCaptureBufferPool::kInvalidId;
ncarter (slow) 2013/11/07 02:25:28 If you want to protect against misuse of buffer_id
sheu 2013/11/08 19:26:32 I think I just went a little overboard with the gh
506
453 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { 507 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) {
454 BrowserThread::PostTask(BrowserThread::IO, 508 BrowserThread::PostTask(BrowserThread::IO,
455 FROM_HERE, 509 FROM_HERE,
456 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, 510 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread,
457 controller_, buffer_id_to_drop)); 511 controller_, buffer_id_to_drop));
512 rotated_buffers_.erase(buffer_id_to_drop);
458 } 513 }
459 return frame; 514
515 // If rotation is required, and the returned frame has not been rotated,
516 // perform a clear to clear the letterbox borders.
517 if ((rotation % 180) == 0) {
jiayl 2013/11/08 22:16:46 why 180 not 360? Could you add comments to explain
sheu 2013/11/09 00:59:30 Updated comment. Basically: a 180 degree rotation
518 rotated_buffers_.erase(buffer_id);
ncarter (slow) 2013/11/07 02:25:28 ... [continued] to avoid the bugs like this (buffe
sheu 2013/11/08 19:26:32 /le sigh Done.
519 } else {
520 if (!rotated_buffers_.count(buffer_id)) {
ncarter (slow) 2013/11/07 02:25:28 You can make this an .insert(); the return value w
sheu 2013/11/08 19:26:32 Done.
521 // TODO(jiayl): Generalize the |rotation| mechanism.
jiayl 2013/11/08 22:16:46 What does it mean?
sheu 2013/11/09 00:59:30 This block is copied out from the VideoCaptureBuff
ncarter (slow) 2013/11/09 01:10:34 Just remove the TODO. You've mostly accomplished i
sheu 2013/11/11 22:37:44 Done.
522 memset(output_buffer->data(), 0, output_buffer->size());
523 rotated_buffers_.insert(buffer_id);
524 }
525 }
526
527 return output_buffer;
460 } 528 }
461 529
462 VideoCaptureController::~VideoCaptureController() { 530 VideoCaptureController::~VideoCaptureController() {
463 STLDeleteContainerPointers(controller_clients_.begin(), 531 STLDeleteContainerPointers(controller_clients_.begin(),
464 controller_clients_.end()); 532 controller_clients_.end());
465 } 533 }
466 534
467 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( 535 void VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread(
468 const scoped_refptr<media::VideoFrame>& reserved_frame, 536 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer,
537 const gfx::Size& dimensions,
469 int frame_rate, 538 int frame_rate,
470 base::Time timestamp) { 539 base::Time timestamp) {
471 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 540 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
472 541
473 int buffer_id = buffer_pool_->RecognizeReservedBuffer( 542 int buffer_id = buffer_pool_->RecognizeReservedBuffer(buffer->data());
474 reserved_frame->shared_memory_handle());
475 if (buffer_id < 0) { 543 if (buffer_id < 0) {
476 NOTREACHED(); 544 NOTREACHED();
477 return; 545 return;
478 } 546 }
479 547
548 // |buffer_id| will remain valid as long as |buffer| remains valid, so
549 // it will be valid for the remainder of this function.
550
480 media::VideoCaptureFormat frame_format( 551 media::VideoCaptureFormat frame_format(
481 reserved_frame->coded_size().width(), 552 dimensions.width(),
482 reserved_frame->coded_size().height(), 553 dimensions.height(),
483 frame_rate, 554 frame_rate,
484 media::VariableResolutionVideoCaptureDevice); 555 media::VariableResolutionVideoCaptureDevice);
485 556
486 int count = 0; 557 int count = 0;
487 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 558 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
488 for (ControllerClients::iterator client_it = controller_clients_.begin(); 559 for (ControllerClients::iterator client_it = controller_clients_.begin();
489 client_it != controller_clients_.end(); ++client_it) { 560 client_it != controller_clients_.end(); ++client_it) {
490 ControllerClient* client = *client_it; 561 ControllerClient* client = *client_it;
491 if (client->session_closed) 562 if (client->session_closed)
492 continue; 563 continue;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 } 644 }
574 return NULL; 645 return NULL;
575 } 646 }
576 647
577 int VideoCaptureController::GetClientCount() { 648 int VideoCaptureController::GetClientCount() {
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
579 return controller_clients_.size(); 650 return controller_clients_.size();
580 } 651 }
581 652
582 } // namespace content 653 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698