blob: 0f36b69eb6c82b2eb1f43cd30de5e6de8808ba4d [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/capture/video/chromeos/vendor_tag_ops_delegate.h"
#include <utility>
#include "base/bind.h"
#include "base/strings/strcat.h"
namespace media {
VendorTagOpsDelegate::VendorTagOpsDelegate(
scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner)
: ipc_task_runner_(ipc_task_runner), is_initializing_(false) {}
VendorTagOpsDelegate::~VendorTagOpsDelegate() = default;
mojo::PendingReceiver<cros::mojom::VendorTagOps>
VendorTagOpsDelegate::MakeReceiver() {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
auto receiver = vendor_tag_ops_.BindNewPipeAndPassReceiver();
vendor_tag_ops_.set_disconnect_handler(
base::BindOnce(&VendorTagOpsDelegate::Reset, base::Unretained(this)));
return receiver;
}
void VendorTagOpsDelegate::Initialize() {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
base::AutoLock lock(lock_);
is_initializing_ = true;
vendor_tag_ops_->GetTagCount(base::BindOnce(
&VendorTagOpsDelegate::OnGotTagCount, base::Unretained(this)));
}
void VendorTagOpsDelegate::Reset() {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
base::AutoLock lock(lock_);
vendor_tag_ops_.reset();
pending_info_.clear();
name_map_.clear();
tag_map_.clear();
initialized_.Reset();
is_initializing_ = false;
}
void VendorTagOpsDelegate::StopInitialization() {
base::AutoLock lock(lock_);
initialized_.Signal();
is_initializing_ = false;
}
void VendorTagOpsDelegate::RemovePending(uint32_t tag) {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
size_t removed = pending_info_.erase(tag);
DCHECK_EQ(removed, 1u);
if (pending_info_.empty()) {
DVLOG(1) << "VendorTagOpsDelegate initialized";
StopInitialization();
}
}
void VendorTagOpsDelegate::OnGotTagCount(int32_t tag_count) {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
if (tag_count == -1) {
LOG(ERROR) << "Failed to get tag count";
StopInitialization();
return;
}
if (tag_count == 0) {
// There is no vendor tag, we are done here.
StopInitialization();
return;
}
vendor_tag_ops_->GetAllTags(base::BindOnce(
&VendorTagOpsDelegate::OnGotAllTags, base::Unretained(this), tag_count));
}
void VendorTagOpsDelegate::OnGotAllTags(size_t tag_count,
const std::vector<uint32_t>& tags) {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
DCHECK_EQ(tags.size(), tag_count);
for (uint32_t tag : tags) {
pending_info_[tag].tag = static_cast<cros::mojom::CameraMetadataTag>(tag);
vendor_tag_ops_->GetSectionName(
tag, base::BindOnce(&VendorTagOpsDelegate::OnGotSectionName,
base::Unretained(this), tag));
}
}
void VendorTagOpsDelegate::OnGotSectionName(
uint32_t tag,
const absl::optional<std::string>& section_name) {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
if (!section_name.has_value()) {
LOG(ERROR) << "Failed to get section name of tag " << std::hex
<< std::showbase << tag;
RemovePending(tag);
return;
}
pending_info_[tag].section_name = *section_name;
vendor_tag_ops_->GetTagName(
tag, base::BindOnce(&VendorTagOpsDelegate::OnGotTagName,
base::Unretained(this), tag));
}
void VendorTagOpsDelegate::OnGotTagName(
uint32_t tag,
const absl::optional<std::string>& tag_name) {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
if (!tag_name.has_value()) {
LOG(ERROR) << "Failed to get tag name of tag " << std::hex << std::showbase
<< tag;
RemovePending(tag);
return;
}
pending_info_[tag].tag_name = *tag_name;
vendor_tag_ops_->GetTagType(
tag, base::BindOnce(&VendorTagOpsDelegate::OnGotTagType,
base::Unretained(this), tag));
}
void VendorTagOpsDelegate::OnGotTagType(uint32_t tag, int32_t type) {
DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
if (type == -1) {
LOG(ERROR) << "Failed to get tag type of tag " << std::hex << std::showbase
<< tag;
RemovePending(tag);
return;
}
VendorTagInfo& info = pending_info_[tag];
info.type = static_cast<cros::mojom::EntryType>(type);
std::string full_name = base::StrCat({info.section_name, ".", info.tag_name});
name_map_[full_name] = info;
RemovePending(tag);
}
const VendorTagInfo* VendorTagOpsDelegate::GetInfoByName(
const std::string& full_name) {
{
base::AutoLock lock(lock_);
if (!is_initializing_ && !initialized_.IsSignaled()) {
LOG(WARNING) << "VendorTagOps is accessed before calling Initialize()";
return nullptr;
}
}
initialized_.Wait();
auto it = name_map_.find(full_name);
if (it == name_map_.end()) {
return nullptr;
}
return &it->second;
}
const VendorTagInfo* VendorTagOpsDelegate::GetInfoByTag(
cros::mojom::CameraMetadataTag tag) {
{
base::AutoLock lock(lock_);
if (!is_initializing_ && !initialized_.IsSignaled()) {
LOG(WARNING) << "VendorTagOps is accessed before calling Initialize()";
return nullptr;
}
}
initialized_.Wait();
auto it = tag_map_.find(tag);
if (it == tag_map_.end()) {
return nullptr;
}
return &it->second;
}
} // namespace media