| // Copyright 2017 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/fake_mjpeg_decode_accelerator.h" |
| |
| #include <utility> |
| |
| #include "base/functional/bind.h" |
| #include "base/logging.h" |
| #include "base/memory/shared_memory_mapping.h" |
| #include "base/memory/unsafe_shared_memory_region.h" |
| #include "base/task/bind_post_task.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "media/base/video_frame.h" |
| #include "media/base/video_types.h" |
| |
| namespace chromeos_camera { |
| |
| FakeMjpegDecodeAccelerator::FakeMjpegDecodeAccelerator( |
| const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
| : client_task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()), |
| io_task_runner_(std::move(io_task_runner)), |
| decoder_thread_("FakeMjpegDecoderThread") {} |
| |
| FakeMjpegDecodeAccelerator::~FakeMjpegDecodeAccelerator() { |
| DCHECK(client_task_runner_->BelongsToCurrentThread()); |
| } |
| |
| void FakeMjpegDecodeAccelerator::InitializeOnTaskRunner( |
| MjpegDecodeAccelerator::Client* client, |
| InitCB init_cb) { |
| DCHECK(client_task_runner_->BelongsToCurrentThread()); |
| client_ = client; |
| |
| if (!decoder_thread_.Start()) { |
| DLOG(ERROR) << "Failed to start decoding thread."; |
| std::move(init_cb).Run(false); |
| return; |
| } |
| |
| decoder_task_runner_ = decoder_thread_.task_runner(); |
| std::move(init_cb).Run(true); |
| } |
| |
| void FakeMjpegDecodeAccelerator::InitializeAsync( |
| MjpegDecodeAccelerator::Client* client, |
| InitCB init_cb) { |
| DCHECK(client_task_runner_->BelongsToCurrentThread()); |
| |
| client_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&FakeMjpegDecodeAccelerator::InitializeOnTaskRunner, |
| weak_factory_.GetWeakPtr(), client, |
| base::BindPostTaskToCurrentDefault(std::move(init_cb)))); |
| } |
| |
| void FakeMjpegDecodeAccelerator::Decode( |
| media::BitstreamBuffer bitstream_buffer, |
| scoped_refptr<media::VideoFrame> video_frame) { |
| DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| |
| base::UnsafeSharedMemoryRegion src_shm_region = bitstream_buffer.TakeRegion(); |
| base::WritableSharedMemoryMapping src_shm_mapping = |
| src_shm_region.MapAt(bitstream_buffer.offset(), bitstream_buffer.size()); |
| if (!src_shm_mapping.IsValid()) { |
| DLOG(ERROR) << "Unable to map shared memory in FakeMjpegDecodeAccelerator"; |
| NotifyError(bitstream_buffer.id(), |
| MjpegDecodeAccelerator::UNREADABLE_INPUT); |
| return; |
| } |
| |
| // Unretained |this| is safe because |this| owns |decoder_thread_|. |
| decoder_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&FakeMjpegDecodeAccelerator::DecodeOnDecoderThread, |
| base::Unretained(this), bitstream_buffer.id(), |
| std::move(video_frame), std::move(src_shm_mapping))); |
| } |
| |
| void FakeMjpegDecodeAccelerator::Decode( |
| int32_t task_id, |
| base::ScopedFD src_dmabuf_fd, |
| size_t src_size, |
| off_t src_offset, |
| scoped_refptr<media::VideoFrame> dst_frame) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void FakeMjpegDecodeAccelerator::DecodeOnDecoderThread( |
| int32_t task_id, |
| scoped_refptr<media::VideoFrame> video_frame, |
| base::WritableSharedMemoryMapping src_shm_mapping) { |
| DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
| |
| // Do not actually decode the Jpeg data. |
| // Instead, just fill the output buffer with zeros. |
| size_t allocation_size = media::VideoFrame::AllocationSize( |
| media::PIXEL_FORMAT_I420, video_frame->coded_size()); |
| memset(video_frame->writable_data(0), 0, allocation_size); |
| |
| client_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&FakeMjpegDecodeAccelerator::OnDecodeDoneOnClientThread, |
| weak_factory_.GetWeakPtr(), task_id)); |
| } |
| |
| bool FakeMjpegDecodeAccelerator::IsSupported() { |
| return true; |
| } |
| |
| void FakeMjpegDecodeAccelerator::NotifyError(int32_t task_id, Error error) { |
| client_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&FakeMjpegDecodeAccelerator::NotifyErrorOnClientThread, |
| weak_factory_.GetWeakPtr(), task_id, error)); |
| } |
| |
| void FakeMjpegDecodeAccelerator::NotifyErrorOnClientThread(int32_t task_id, |
| Error error) { |
| DCHECK(client_task_runner_->BelongsToCurrentThread()); |
| client_->NotifyError(task_id, error); |
| } |
| |
| void FakeMjpegDecodeAccelerator::OnDecodeDoneOnClientThread(int32_t task_id) { |
| DCHECK(client_task_runner_->BelongsToCurrentThread()); |
| client_->VideoFrameReady(task_id); |
| } |
| |
| } // namespace chromeos_camera |