| Index: content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| diff --git a/content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc b/content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| index 0fa00ea82a960fd7431e63b085e061a1e5d33153..619f6ddc9f2d9c4dee22b0021bd88d7d006886d2 100644
|
| --- a/content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| +++ b/content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| @@ -99,6 +99,7 @@ void InProcessBuildableVideoCaptureDevice::CreateAndStartDeviceAsync(
|
| Callbacks* callbacks,
|
| base::OnceClosure done_cb) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + DCHECK_EQ(State::NO_DEVICE, state_);
|
|
|
| const int max_buffers = (controller->stream_type() == MEDIA_TAB_VIDEO_CAPTURE
|
| ? kMaxNumberOfBuffersForTabCapture
|
| @@ -178,6 +179,7 @@ void InProcessBuildableVideoCaptureDevice::CreateAndStartDeviceAsync(
|
| }
|
|
|
| device_task_runner_->PostTask(FROM_HERE, start_capture_closure);
|
| + state_ = State::DEVICE_START_IN_PROGRESS;
|
| }
|
|
|
| void InProcessBuildableVideoCaptureDevice::ReleaseDeviceAsync(
|
| @@ -185,19 +187,28 @@ void InProcessBuildableVideoCaptureDevice::ReleaseDeviceAsync(
|
| base::OnceClosure done_cb) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| controller->SetConsumerFeedbackObserver(nullptr);
|
| - if (!device_)
|
| - return;
|
| - media::VideoCaptureDevice* device_ptr = device_.release();
|
| -
|
| - bool posting_task_succeeded = device_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&StopAndReleaseDeviceOnDeviceThread, device_ptr,
|
| - base::Bind([](scoped_refptr<base::SingleThreadTaskRunner>) {},
|
| - device_task_runner_)));
|
| - if (posting_task_succeeded == false) {
|
| - // Since posting to the task runner has failed, we attempt doing it on
|
| - // the calling thread instead.
|
| - StopAndReleaseDeviceOnDeviceThread(device_ptr, base::Bind([]() {}));
|
| + switch (state_) {
|
| + case State::DEVICE_START_IN_PROGRESS:
|
| + state_ = State::DEVICE_START_ABORTING;
|
| + return;
|
| + case State::NO_DEVICE:
|
| + case State::DEVICE_START_ABORTING:
|
| + return;
|
| + case State::DEVICE_STARTED:
|
| + media::VideoCaptureDevice* device_ptr = device_.release();
|
| + bool posting_task_succeeded = device_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &StopAndReleaseDeviceOnDeviceThread, device_ptr,
|
| + base::Bind([](scoped_refptr<base::SingleThreadTaskRunner>) {},
|
| + device_task_runner_)));
|
| + if (posting_task_succeeded == false) {
|
| + // Since posting to the task runner has failed, we attempt doing it on
|
| + // the calling thread instead.
|
| + StopAndReleaseDeviceOnDeviceThread(device_ptr, base::Bind([]() {}));
|
| + }
|
| + state_ = State::NO_DEVICE;
|
| + return;
|
| }
|
| base::ResetAndReturn(&done_cb).Run();
|
| }
|
| @@ -294,13 +305,11 @@ InProcessBuildableVideoCaptureDevice::CreateDeviceClient(
|
| base::WeakPtr<media::VideoFrameReceiver> receiver) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - scoped_refptr<media::VideoCaptureBufferPool> buffer_pool_ =
|
| + return base::MakeUnique<media::VideoCaptureDeviceClient>(
|
| + base::MakeUnique<VideoFrameReceiverOnIOThread>(receiver),
|
| new media::VideoCaptureBufferPoolImpl(
|
| base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(),
|
| - buffer_pool_max_buffer_count);
|
| -
|
| - return base::MakeUnique<media::VideoCaptureDeviceClient>(
|
| - base::MakeUnique<VideoFrameReceiverOnIOThread>(receiver), buffer_pool_,
|
| + buffer_pool_max_buffer_count),
|
| base::Bind(&CreateGpuJpegDecoder,
|
| base::Bind(&media::VideoFrameReceiver::OnFrameReadyInBuffer,
|
| receiver)));
|
| @@ -312,20 +321,45 @@ void InProcessBuildableVideoCaptureDevice::OnDeviceStarted(
|
| base::OnceClosure done_cb,
|
| std::unique_ptr<media::VideoCaptureDevice> device) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - if (!device) {
|
| - callbacks->OnDeviceStartFailed(controller);
|
| - base::ResetAndReturn(&done_cb).Run();
|
| - return;
|
| + switch (state_) {
|
| + case State::DEVICE_START_IN_PROGRESS:
|
| + if (!device) {
|
| + state_ = State::NO_DEVICE;
|
| + callbacks->OnDeviceStartFailed(controller);
|
| + base::ResetAndReturn(&done_cb).Run();
|
| + return;
|
| + }
|
| + // Passing raw pointer |device.get()| to the controller is safe,
|
| + // because we take ownership of |device| and we call
|
| + // controller->SetConsumerFeedbackObserver(nullptr) before releasing
|
| + // |device|.
|
| + controller->SetConsumerFeedbackObserver(
|
| + base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>(
|
| + device.get(), device_task_runner_));
|
| + device_ = std::move(device);
|
| + state_ = State::DEVICE_STARTED;
|
| + callbacks->DidStartDevice(controller);
|
| + base::ResetAndReturn(&done_cb).Run();
|
| + return;
|
| + case State::DEVICE_START_ABORTING:
|
| + if (device) {
|
| + device_ = std::move(device);
|
| + state_ = State::DEVICE_STARTED;
|
| + // We do not move our |done_cb| to this invocation, because
|
| + // we still need it to stay alive for the remainder of this method
|
| + // execution. Our implementation of ReleaseDeviceAsync() does not
|
| + // actually need the context while releasing the device.
|
| + ReleaseDeviceAsync(controller, base::Bind([]() {}));
|
| + }
|
| + state_ = State::NO_DEVICE;
|
| + callbacks->OnDeviceStartAborted();
|
| + base::ResetAndReturn(&done_cb).Run();
|
| + return;
|
| + case State::NO_DEVICE:
|
| + case State::DEVICE_STARTED:
|
| + NOTREACHED();
|
| + return;
|
| }
|
| - // Passing raw pointer |device.get()| to the controller is safe,
|
| - // because we take ownership of |device| and we call
|
| - // controller->SetConsumerFeedbackObserver(nullptr) before releasing |device|.
|
| - controller->SetConsumerFeedbackObserver(
|
| - base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>(
|
| - device.get(), device_task_runner_));
|
| - device_ = std::move(device);
|
| - callbacks->DidStartDevice(controller);
|
| - base::ResetAndReturn(&done_cb).Run();
|
| }
|
|
|
| void InProcessBuildableVideoCaptureDevice::DoStartDeviceCaptureOnDeviceThread(
|
|
|