diff options
Diffstat (limited to 'chromium/media')
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; } |