1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// 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/compiler_specific.h"
#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());
UNSAFE_TODO(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
|