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

Unified Diff: content/browser/renderer_host/media/video_capture_controller.cc

Issue 24133002: Make VideoCaptureController single-threaded and not ref counted. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: git pull Created 7 years, 3 months 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/media/video_capture_controller.cc
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index dbafeba49223d38b2edec3f738977f6241e8898c..454864cc1b9ce5dcefe45875d4f47aae7c233e62 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -93,14 +93,79 @@ struct VideoCaptureController::ControllerClient {
bool session_closed;
};
+// Receives events from the VideoCaptureDevice and posts them to a
+// VideoCaptureController on the IO thread. An instance of this class may safely
+// outlive its target VideoCaptureController.
+//
+// Methods of this class may be called from any thread, and in practice will
+// often be called on some auxiliary thread depending on the platform and the
+// device type; including, for example, the DirectShow thread on Windows, the
+// v4l2_thread on Linux, and the UI thread for tab capture.
+class VideoCaptureController::VideoCaptureDeviceClient
+ : public media::VideoCaptureDevice::EventHandler {
+ public:
+ explicit VideoCaptureDeviceClient(
+ const base::WeakPtr<VideoCaptureController>& controller);
+ virtual ~VideoCaptureDeviceClient();
+
+ // VideoCaptureDevice::EventHandler implementation.
+ virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE;
+ virtual void OnIncomingCapturedFrame(const uint8* data,
+ int length,
+ base::Time timestamp,
+ int rotation,
+ bool flip_vert,
+ bool flip_horiz) OVERRIDE;
+ virtual void OnIncomingCapturedVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame,
+ base::Time timestamp) OVERRIDE;
+ virtual void OnError() OVERRIDE;
+ virtual void OnFrameInfo(
+ const media::VideoCaptureCapability& info) OVERRIDE;
+ virtual void OnFrameInfoChanged(
+ const media::VideoCaptureCapability& info) OVERRIDE;
+
+ private:
+ // The controller to which we post events.
+ const base::WeakPtr<VideoCaptureController> controller_;
+
+ // The pool of shared-memory buffers used for capturing.
+ scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
+
+ // Chopped pixels in width/height in case video capture device has odd
+ // numbers for width/height.
+ int chopped_width_;
+ int chopped_height_;
+
+ // Tracks the current frame format.
+ media::VideoCaptureCapability frame_info_;
+};
+
VideoCaptureController::VideoCaptureController()
- : chopped_width_(0),
- chopped_height_(0),
- frame_info_available_(false),
- state_(VIDEO_CAPTURE_STATE_STARTED) {
+ : state_(VIDEO_CAPTURE_STATE_STARTED),
wjia(left Chromium) 2013/09/18 01:29:02 |state_| is not really needed any more since there
+ weak_ptr_factory_(this) {
memset(&current_params_, 0, sizeof(current_params_));
}
+VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
+ const base::WeakPtr<VideoCaptureController>& controller)
+ : controller_(controller),
+ chopped_width_(0),
+ chopped_height_(0) {}
+
+VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
+
+base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+scoped_ptr<media::VideoCaptureDevice::EventHandler>
+VideoCaptureController::NewDeviceClient() {
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> result(
+ new VideoCaptureDeviceClient(this->GetWeakPtr()));
+ return result.Pass();
+}
+
void VideoCaptureController::AddClient(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
@@ -129,7 +194,7 @@ void VideoCaptureController::AddClient(
// If we already have gotten frame_info from the device, repeat it to the new
// client.
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
- if (frame_info_available_) {
+ if (frame_info_.IsValid()) {
SendFrameInfoAndBuffers(client);
}
controller_clients_.push_back(client);
@@ -165,8 +230,7 @@ int VideoCaptureController::RemoveClient(
return session_id;
}
-void VideoCaptureController::StopSession(
- int session_id) {
+void VideoCaptureController::StopSession(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id;
@@ -198,20 +262,15 @@ void VideoCaptureController::ReturnBuffer(
buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
}
-scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveOutputBuffer() {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return NULL;
+scoped_refptr<media::VideoFrame>
+VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer() {
return buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
frame_info_.height),
0);
}
-// Implements VideoCaptureDevice::EventHandler.
-// OnIncomingCapturedFrame is called the thread running the capture device.
-// I.e.- DirectShow thread on windows and v4l2_thread on Linux.
#if !defined(OS_IOS) && !defined(OS_ANDROID)
-void VideoCaptureController::OnIncomingCapturedFrame(
+void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
const uint8* data,
int length,
base::Time timestamp,
@@ -220,14 +279,10 @@ void VideoCaptureController::OnIncomingCapturedFrame(
bool flip_horiz) {
TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
- scoped_refptr<media::VideoFrame> dst;
- {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return;
- dst = buffer_pool_->ReserveI420VideoFrame(
- gfx::Size(frame_info_.width, frame_info_.height), rotation);
- }
+ if (!buffer_pool_.get())
+ return;
+ scoped_refptr<media::VideoFrame> dst = buffer_pool_->ReserveI420VideoFrame(
+ gfx::Size(frame_info_.width, frame_info_.height), rotation);
if (!dst.get())
return;
@@ -336,12 +391,12 @@ void VideoCaptureController::OnIncomingCapturedFrame(
BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this,
+ controller_,
dst,
timestamp));
}
#else
-void VideoCaptureController::OnIncomingCapturedFrame(
+void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
const uint8* data,
int length,
base::Time timestamp,
@@ -354,15 +409,12 @@ void VideoCaptureController::OnIncomingCapturedFrame(
TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
- scoped_refptr<media::VideoFrame> dst;
- {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return;
- dst = buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- rotation);
- }
+ if (!buffer_pool_)
+ return;
+ scoped_refptr<media::VideoFrame> dst =
+ buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
+ frame_info_.height),
+ rotation);
if (!dst.get())
return;
@@ -426,39 +478,36 @@ void VideoCaptureController::OnIncomingCapturedFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, dst, timestamp));
+ controller_, dst, timestamp));
}
#endif // #if !defined(OS_IOS) && !defined(OS_ANDROID)
-// OnIncomingCapturedVideoFrame is called the thread running the capture device.
-void VideoCaptureController::OnIncomingCapturedVideoFrame(
+void
+VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
const scoped_refptr<media::VideoFrame>& frame,
base::Time timestamp) {
- scoped_refptr<media::VideoFrame> target;
- {
- base::AutoLock lock(buffer_pool_lock_);
-
- if (!buffer_pool_.get())
- return;
-
- // If this is a frame that belongs to the buffer pool, we can forward it
- // directly to the IO thread and be done.
- if (buffer_pool_->RecognizeReservedBuffer(
- frame->shared_memory_handle()) >= 0) {
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, frame, timestamp));
- return;
- }
- // Otherwise, this is a frame that belongs to the caller, and we must copy
- // it to a frame from the buffer pool.
- target = buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- 0);
+ if (!buffer_pool_)
+ return;
+
+ // If this is a frame that belongs to the buffer pool, we can forward it
+ // directly to the IO thread and be done.
+ if (buffer_pool_->RecognizeReservedBuffer(
+ frame->shared_memory_handle()) >= 0) {
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
+ controller_, frame, timestamp));
+ return;
}
+ // Otherwise, this is a frame that belongs to the caller, and we must copy
+ // it to a frame from the buffer pool.
+ scoped_refptr<media::VideoFrame> target =
+ buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
+ frame_info_.height),
+ 0);
+
if (!target.get())
return;
@@ -545,18 +594,18 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, target, timestamp));
+ controller_, target, timestamp));
}
-void VideoCaptureController::OnError() {
+void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoErrorOnIOThread, this));
+ base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
}
-void VideoCaptureController::OnFrameInfo(
+void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
const media::VideoCaptureCapability& info) {
- frame_info_= info;
+ frame_info_ = info;
// Handle cases when |info| has odd numbers for width/height.
if (info.width & 1) {
--frame_info_.width;
@@ -570,17 +619,38 @@ void VideoCaptureController::OnFrameInfo(
} else {
chopped_height_ = 0;
}
+
+ DCHECK(!buffer_pool_.get());
+
+ // TODO(nick): Give BufferPool the same lifetime as the controller, have it
+ // support frame size changes, and stop checking it for NULL everywhere.
+ // http://crbug.com/266082
+ buffer_pool_ = new VideoCaptureBufferPool(
+ media::VideoFrame::AllocationSize(
+ media::VideoFrame::I420,
+ gfx::Size(frame_info_.width, frame_info_.height)),
+ kNoOfBuffers);
+
+ // Check whether all buffers were created successfully.
+ if (!buffer_pool_->Allocate()) {
+ // Transition to the error state.
+ buffer_pool_ = NULL;
+ OnError();
+ return;
+ }
+
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this));
+ base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, controller_,
+ frame_info_, buffer_pool_));
}
-void VideoCaptureController::OnFrameInfoChanged(
+void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
const media::VideoCaptureCapability& info) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoFrameInfoChangedOnIOThread,
- this, info));
+ controller_, info));
}
VideoCaptureController::~VideoCaptureController() {
@@ -621,7 +691,9 @@ void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
buffer_pool_->HoldForConsumers(buffer_id, count);
}
-void VideoCaptureController::DoFrameInfoOnIOThread() {
+void VideoCaptureController::DoFrameInfoOnIOThread(
+ const media::VideoCaptureCapability& frame_info,
+ const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!buffer_pool_.get()) << "Frame info should happen only once.";
@@ -629,24 +701,8 @@ void VideoCaptureController::DoFrameInfoOnIOThread() {
if (state_ != VIDEO_CAPTURE_STATE_STARTED)
return;
- scoped_refptr<VideoCaptureBufferPool> buffer_pool =
- new VideoCaptureBufferPool(
- media::VideoFrame::AllocationSize(
- media::VideoFrame::I420,
- gfx::Size(frame_info_.width, frame_info_.height)),
- kNoOfBuffers);
-
- // Check whether all buffers were created successfully.
- if (!buffer_pool->Allocate()) {
- DoErrorOnIOThread();
- return;
- }
-
- {
- base::AutoLock lock(buffer_pool_lock_);
- buffer_pool_ = buffer_pool;
- }
- frame_info_available_ = true;
+ frame_info_ = frame_info;
+ buffer_pool_ = buffer_pool;
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
@@ -690,7 +746,7 @@ void VideoCaptureController::DoErrorOnIOThread() {
void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(frame_info_available_);
+ DCHECK(frame_info_.IsValid());
client->event_handler->OnFrameInfo(client->controller_id,
frame_info_);
for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) {

Powered by Google App Engine
This is Rietveld 408576698