summaryrefslogtreecommitdiff
path: root/chromium/media
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media')
-rw-r--r--chromium/media/capture/video/chromeos/camera_device_delegate.cc15
-rw-r--r--chromium/media/capture/video/chromeos/camera_device_delegate.h4
-rw-r--r--chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc42
-rw-r--r--chromium/media/capture/video/chromeos/video_capture_device_arc_chromeos.cc3
-rw-r--r--chromium/media/filters/ffmpeg_demuxer.cc15
-rw-r--r--chromium/media/gpu/v4l2/v4l2_video_decode_accelerator.cc11
6 files changed, 75 insertions, 15 deletions
diff --git a/chromium/media/capture/video/chromeos/camera_device_delegate.cc b/chromium/media/capture/video/chromeos/camera_device_delegate.cc
index 0383a05f4c6..1d489a12d33 100644
--- a/chromium/media/capture/video/chromeos/camera_device_delegate.cc
+++ b/chromium/media/capture/video/chromeos/camera_device_delegate.cc
@@ -86,14 +86,13 @@ void CameraDeviceDelegate::AllocateAndStart(
}
void CameraDeviceDelegate::StopAndDeAllocate(
- base::Closure device_close_callback) {
+ base::OnceClosure device_close_callback) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- // StopAndDeAllocate may be called at any state except
- // CameraDeviceContext::State::kStopping.
- DCHECK_NE(device_context_->GetState(), CameraDeviceContext::State::kStopping);
- if (device_context_->GetState() == CameraDeviceContext::State::kStopped ||
- !stream_buffer_manager_) {
+ if (!device_context_ ||
+ device_context_->GetState() == CameraDeviceContext::State::kStopped ||
+ (device_context_->GetState() == CameraDeviceContext::State::kError &&
+ !stream_buffer_manager_)) {
// In case of Mojo connection error the device may be stopped before
// StopAndDeAllocate is called; in case of device open failure, the state
// is set to kError and |stream_buffer_manager_| is uninitialized.
@@ -101,6 +100,10 @@ void CameraDeviceDelegate::StopAndDeAllocate(
return;
}
+ // StopAndDeAllocate may be called at any state except
+ // CameraDeviceContext::State::kStopping.
+ DCHECK_NE(device_context_->GetState(), CameraDeviceContext::State::kStopping);
+
device_close_callback_ = std::move(device_close_callback);
device_context_->SetState(CameraDeviceContext::State::kStopping);
if (!device_ops_.is_bound()) {
diff --git a/chromium/media/capture/video/chromeos/camera_device_delegate.h b/chromium/media/capture/video/chromeos/camera_device_delegate.h
index 9c062e04216..9cff56adbcf 100644
--- a/chromium/media/capture/video/chromeos/camera_device_delegate.h
+++ b/chromium/media/capture/video/chromeos/camera_device_delegate.h
@@ -66,7 +66,7 @@ class CAPTURE_EXPORT CameraDeviceDelegate final {
// Delegation methods for the VideoCaptureDevice interface.
void AllocateAndStart(const VideoCaptureParams& params,
CameraDeviceContext* device_context);
- void StopAndDeAllocate(base::Closure device_close_callback);
+ void StopAndDeAllocate(base::OnceClosure device_close_callback);
void TakePhoto(VideoCaptureDevice::TakePhotoCallback callback);
void GetPhotoState(VideoCaptureDevice::GetPhotoStateCallback callback);
void SetPhotoOptions(mojom::PhotoSettingsPtr settings,
@@ -162,7 +162,7 @@ class CAPTURE_EXPORT CameraDeviceDelegate final {
// Where all the Mojo IPC calls takes place.
const scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
- base::Closure device_close_callback_;
+ base::OnceClosure device_close_callback_;
base::WeakPtrFactory<CameraDeviceDelegate> weak_ptr_factory_;
diff --git a/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc b/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc
index 8103886fd20..8a0316b94a2 100644
--- a/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc
+++ b/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc
@@ -576,4 +576,46 @@ TEST_F(CameraDeviceDelegateTest, FailToOpenDevice) {
ResetDevice();
}
+// Test that the class handles it correctly when StopAndDeAllocate is called
+// multiple times.
+TEST_F(CameraDeviceDelegateTest, DoubleStopAndDeAllocate) {
+ AllocateDeviceWithDescriptor(kDefaultDescriptor);
+
+ VideoCaptureParams params;
+ params.requested_format = kDefaultCaptureFormat;
+
+ auto* mock_client = ResetDeviceContext();
+ mock_client->SetFrameCb(BindToCurrentLoop(base::BindOnce(
+ &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
+ mock_client->SetQuitCb(BindToCurrentLoop(base::BindOnce(
+ &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
+ SetUpExpectationUntilCapturing(mock_client);
+ SetUpExpectationForCaptureLoop();
+
+ device_delegate_thread_.task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
+ camera_device_delegate_->GetWeakPtr(), params,
+ base::Unretained(device_context_.get())));
+
+ // Wait until a frame is received. MockVideoCaptureClient calls QuitRunLoop()
+ // to stop the run loop.
+ DoLoop();
+
+ EXPECT_EQ(CameraDeviceContext::State::kCapturing, GetState());
+
+ SetUpExpectationForClose();
+
+ WaitForDeviceToClose();
+
+ device_delegate_thread_.task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&CameraDeviceDelegate::StopAndDeAllocate,
+ camera_device_delegate_->GetWeakPtr(),
+ BindToCurrentLoop(base::BindOnce(
+ &CameraDeviceDelegateTest::QuitRunLoop,
+ base::Unretained(this)))));
+ DoLoop();
+
+ ResetDevice();
+}
+
} // namespace media
diff --git a/chromium/media/capture/video/chromeos/video_capture_device_arc_chromeos.cc b/chromium/media/capture/video/chromeos/video_capture_device_arc_chromeos.cc
index 91da489c4a9..934c117cc25 100644
--- a/chromium/media/capture/video/chromeos/video_capture_device_arc_chromeos.cc
+++ b/chromium/media/capture/video/chromeos/video_capture_device_arc_chromeos.cc
@@ -136,6 +136,9 @@ void VideoCaptureDeviceArcChromeOS::SuspendDone(
void VideoCaptureDeviceArcChromeOS::OpenDevice() {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
+ if (!camera_device_delegate_) {
+ return;
+ }
// It's safe to pass unretained |device_context_| here since
// VideoCaptureDeviceArcChromeOS owns |camera_device_delegate_| and makes
// sure |device_context_| outlives |camera_device_delegate_|.
diff --git a/chromium/media/filters/ffmpeg_demuxer.cc b/chromium/media/filters/ffmpeg_demuxer.cc
index 1daed0152f8..2143e474394 100644
--- a/chromium/media/filters/ffmpeg_demuxer.cc
+++ b/chromium/media/filters/ffmpeg_demuxer.cc
@@ -1709,8 +1709,10 @@ void FFmpegDemuxer::OnEnabledAudioTracksChanged(
std::set<FFmpegDemuxerStream*> enabled_streams;
for (const auto& id : track_ids) {
- FFmpegDemuxerStream* stream = track_id_to_demux_stream_map_[id];
- DCHECK(stream);
+ auto it = track_id_to_demux_stream_map_.find(id);
+ if (it == track_id_to_demux_stream_map_.end())
+ continue;
+ FFmpegDemuxerStream* stream = it->second;
DCHECK_EQ(DemuxerStream::AUDIO, stream->type());
// TODO(servolk): Remove after multiple enabled audio tracks are supported
// by the media::RendererImpl.
@@ -1745,9 +1747,12 @@ void FFmpegDemuxer::OnSelectedVideoTrackChanged(
FFmpegDemuxerStream* selected_stream = nullptr;
if (track_id) {
- selected_stream = track_id_to_demux_stream_map_[*track_id];
- DCHECK(selected_stream);
- DCHECK_EQ(DemuxerStream::VIDEO, selected_stream->type());
+ auto it = track_id_to_demux_stream_map_.find(*track_id);
+ if (it != track_id_to_demux_stream_map_.end()) {
+ selected_stream = it->second;
+ DCHECK(selected_stream);
+ DCHECK_EQ(DemuxerStream::VIDEO, selected_stream->type());
+ }
}
// First disable all streams that need to be disabled and then enable the
diff --git a/chromium/media/gpu/v4l2/v4l2_video_decode_accelerator.cc b/chromium/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
index 58bc7bf9059..b6b912ee799 100644
--- a/chromium/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
+++ b/chromium/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
@@ -1270,11 +1270,18 @@ void V4L2VideoDecodeAccelerator::Enqueue() {
// change. They implicitly send a V4L2_DEC_CMD_STOP and V4L2_DEC_CMD_START
// to the decoder.
if (input_buffer_queued_count_ == 0) {
- if (!SendDecoderCmdStop())
- return;
input_ready_queue_.pop();
free_input_buffers_.push_back(buffer);
input_record.input_id = -1;
+ if (coded_size_.IsEmpty()) {
+ // If coded_size_.IsEmpty(), no output buffer could have been
+ // allocated and there is nothing to flush. We can NotifyFlushDone()
+ // immediately, without requesting flush to the driver via
+ // SendDecoderCmdStop().
+ NotifyFlushDoneIfNeeded();
+ } else if (!SendDecoderCmdStop()) {
+ return;
+ }
} else {
break;
}