| // Copyright 2018 The Fuchsia 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 "device_fidl.h" |
| |
| #include <lib/media/codec_impl/codec_admission_control.h> |
| #include "device_ctx.h" |
| |
| #include <threads.h> |
| |
| DeviceFidl::DeviceFidl(DeviceCtx* device) : device_(device) { |
| // Nothing else to do here. |
| } |
| |
| DeviceFidl::~DeviceFidl() { |
| // If we hit this in any useful situation, we'll need to implement this. |
| ZX_ASSERT_MSG(false, "not implemented"); |
| |
| // The DeviceCtx should have already moved over to the shared_fidl_thread() |
| // for this (if ~DeviceCtx implemented), else it's not safe to ~fidl::Binding. |
| // |
| // Also, DeviceFidl::CreateChannelBoundCodecFactory() relies on ability to |
| // post work which will run on shared_fidl_thread() before ~DeviceFidl() |
| // runs on shared_fidl_thread(). |
| ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread()); |
| } |
| |
| void DeviceFidl::CreateChannelBoundCodecFactory(zx::channel* client_endpoint) { |
| zx::channel local_client_endpoint; |
| zx::channel local_server_endpoint; |
| zx_status_t create_status = |
| zx::channel::create(0, &local_client_endpoint, &local_server_endpoint); |
| if (create_status != ZX_OK) { |
| device_->driver()->FatalError("zx::channel::create() failed"); |
| } |
| std::unique_ptr<LocalCodecFactory> factory = |
| std::make_unique<LocalCodecFactory>(device_); |
| factory->SetErrorHandler([this, raw_factory_ptr = factory.get()] { |
| ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread()); |
| auto iter = factories_.find(raw_factory_ptr); |
| ZX_DEBUG_ASSERT(iter != factories_.end()); |
| factories_.erase(iter); |
| }); |
| // Any destruction of "this" is also posted over to shared_fidl_thread(), and |
| // will run after the work posted here runs. |
| // |
| // This posting over to shared_fidl_thread() is mainly for the benefit of |
| // factories_ only being touched from that thread, and secondarily to avoid |
| // taking a dependency on Bind() working from a different thread (both in |
| // Bind() and in DeviceFidl code). |
| device_->driver()->PostToSharedFidl([this, factory = std::move(factory), |
| server_endpoint = std::move( |
| local_server_endpoint)]() mutable { |
| ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread()); |
| LocalCodecFactory* raw_factory_ptr = factory.get(); |
| auto insert_result = |
| factories_.insert(std::make_pair(raw_factory_ptr, std::move(factory))); |
| // insert success |
| ZX_DEBUG_ASSERT(insert_result.second); |
| insert_result.first->second->Bind(std::move(server_endpoint)); |
| }); |
| *client_endpoint = std::move(local_client_endpoint); |
| } |
| |
| void DeviceFidl::BindCodecImpl(std::unique_ptr<CodecImpl> codec) { |
| ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread()); |
| CodecImpl* raw_codec_ptr = codec.get(); |
| auto insert_result = |
| codecs_.insert(std::make_pair(raw_codec_ptr, std::move(codec))); |
| // insert success |
| ZX_DEBUG_ASSERT(insert_result.second); |
| (*insert_result.first).second->BindAsync([this, raw_codec_ptr] { |
| ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread()); |
| auto iter = codecs_.find(raw_codec_ptr); |
| ZX_DEBUG_ASSERT(iter != codecs_.end()); |
| codecs_.erase(iter); |
| }); |
| } |