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