// 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