| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/chromeos_camera/mojo_mjpeg_decode_accelerator.h" |
| |
| #include <stddef.h> |
| |
| #include "base/functional/bind.h" |
| #include "base/logging.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "build/build_config.h" |
| #include "mojo/public/cpp/system/platform_handle.h" |
| |
| namespace chromeos_camera { |
| |
| MojoMjpegDecodeAccelerator::MojoMjpegDecodeAccelerator( |
| scoped_refptr<base::SequencedTaskRunner> io_task_runner, |
| mojo::PendingRemote<chromeos_camera::mojom::MjpegDecodeAccelerator> |
| jpeg_decoder) |
| : io_task_runner_(std::move(io_task_runner)), |
| jpeg_decoder_remote_(std::move(jpeg_decoder)) {} |
| |
| MojoMjpegDecodeAccelerator::~MojoMjpegDecodeAccelerator() { |
| DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); |
| } |
| |
| void MojoMjpegDecodeAccelerator::InitializeAsync( |
| MjpegDecodeAccelerator::Client* client, |
| MjpegDecodeAccelerator::InitCB init_cb) { |
| DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); |
| |
| jpeg_decoder_.Bind(std::move(jpeg_decoder_remote_)); |
| |
| // base::Unretained is safe because |this| owns |jpeg_decoder_|. |
| jpeg_decoder_.set_disconnect_handler( |
| base::BindOnce(&MojoMjpegDecodeAccelerator::OnLostConnectionToJpegDecoder, |
| base::Unretained(this))); |
| jpeg_decoder_->Initialize( |
| base::BindOnce(&MojoMjpegDecodeAccelerator::OnInitializeDone, |
| base::Unretained(this), std::move(init_cb), client)); |
| } |
| |
| void MojoMjpegDecodeAccelerator::Decode( |
| media::BitstreamBuffer bitstream_buffer, |
| media::VideoPixelFormat format, |
| const gfx::Size& coded_size, |
| base::UnsafeSharedMemoryRegion output_region) { |
| DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); |
| DCHECK(jpeg_decoder_.is_bound()); |
| |
| const size_t output_buffer_size = |
| media::VideoFrame::AllocationSize(format, coded_size); |
| DCHECK_GE(output_region.GetSize(), output_buffer_size); |
| |
| mojo::ScopedSharedBufferHandle output_frame_handle = |
| mojo::WrapUnsafeSharedMemoryRegion(std::move(output_region)); |
| if (!output_frame_handle.is_valid()) { |
| DLOG(ERROR) << "Failed to duplicate handle of VideoFrame"; |
| return; |
| } |
| |
| // base::Unretained is safe because |this| owns |jpeg_decoder_|. |
| jpeg_decoder_->Decode(std::move(bitstream_buffer), coded_size, |
| std::move(output_frame_handle), |
| base::checked_cast<uint32_t>(output_buffer_size), |
| base::BindOnce(&MojoMjpegDecodeAccelerator::OnDecodeAck, |
| base::Unretained(this))); |
| } |
| |
| bool MojoMjpegDecodeAccelerator::IsSupported() { |
| return true; |
| } |
| |
| void MojoMjpegDecodeAccelerator::OnInitializeDone( |
| MjpegDecodeAccelerator::InitCB init_cb, |
| MjpegDecodeAccelerator::Client* client, |
| bool success) { |
| DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); |
| |
| if (success) |
| client_ = client; |
| |
| std::move(init_cb).Run(success); |
| } |
| |
| void MojoMjpegDecodeAccelerator::OnDecodeAck( |
| int32_t bitstream_buffer_id, |
| ::chromeos_camera::MjpegDecodeAccelerator::Error error) { |
| DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); |
| |
| if (!client_) |
| return; |
| |
| if (error == ::chromeos_camera::MjpegDecodeAccelerator::Error::NO_ERRORS) { |
| client_->VideoFrameReady(bitstream_buffer_id); |
| return; |
| } |
| |
| // Only NotifyError once. |
| // Client::NotifyError() may trigger deletion of |this|, so calling it needs |
| // to be the last thing done on this stack! |
| MjpegDecodeAccelerator::Client* client = client_; |
| client_ = nullptr; |
| client->NotifyError(bitstream_buffer_id, error); |
| } |
| |
| void MojoMjpegDecodeAccelerator::OnLostConnectionToJpegDecoder() { |
| DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); |
| OnDecodeAck( |
| MjpegDecodeAccelerator::kInvalidTaskId, |
| ::chromeos_camera::MjpegDecodeAccelerator::Error::PLATFORM_FAILURE); |
| } |
| |
| } // namespace chromeos_camera |