blob: a04202528f03e4f290ab1977f6fae7c936e73feb [file] [log] [blame]
// Copyright 2020 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 <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/syslog/cpp/logger.h>
#include <sstream>
#include "src/camera/bin/device/messages.h"
#include "src/camera/bin/device/stream_impl.h"
StreamImpl::Client::Client(StreamImpl& stream, uint64_t id,
fidl::InterfaceRequest<fuchsia::camera3::Stream> request)
: stream_(stream),
id_(id),
loop_(&kAsyncLoopConfigNoAttachToCurrentThread),
binding_(this, std::move(request), loop_.dispatcher()) {
FX_LOGS(DEBUG) << "Stream client " << id << " connected.";
binding_.set_error_handler(fit::bind_member(this, &StreamImpl::Client::OnClientDisconnected));
std::ostringstream oss;
oss << "Camera Stream Thread (Client ID = " << id << ")";
ZX_ASSERT(loop_.StartThread(oss.str().c_str()) == ZX_OK);
}
StreamImpl::Client::~Client() { loop_.Shutdown(); }
void StreamImpl::Client::PostSendFrame(fuchsia::camera3::FrameInfo frame) {
ZX_ASSERT(async::PostTask(loop_.dispatcher(), [this, frame = std::move(frame)]() mutable {
frame_callback_(std::move(frame));
frame_callback_ = nullptr;
}) == ZX_OK);
}
void StreamImpl::Client::PostReceiveBufferCollection(
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token) {
ZX_ASSERT(async::PostTask(loop_.dispatcher(), [this, token = std::move(token)]() mutable {
buffers_.Set(std::move(token));
}) == ZX_OK);
}
bool& StreamImpl::Client::Participant() { return participant_; }
void StreamImpl::Client::OnClientDisconnected(zx_status_t status) {
FX_PLOGS(DEBUG, status) << "Stream client " << id_ << " disconnected.";
stream_.PostRemoveClient(id_);
}
void StreamImpl::Client::CloseConnection(zx_status_t status) {
binding_.Close(status);
stream_.PostRemoveClient(id_);
}
void StreamImpl::Client::SetCropRegion(std::unique_ptr<fuchsia::math::RectF> region) {
CloseConnection(ZX_ERR_NOT_SUPPORTED);
}
void StreamImpl::Client::WatchCropRegion(WatchCropRegionCallback callback) {
CloseConnection(ZX_ERR_NOT_SUPPORTED);
}
void StreamImpl::Client::SetResolution(fuchsia::math::Size coded_size) {
CloseConnection(ZX_ERR_NOT_SUPPORTED);
}
void StreamImpl::Client::WatchResolution(WatchResolutionCallback callback) {
CloseConnection(ZX_ERR_NOT_SUPPORTED);
}
void StreamImpl::Client::SetBufferCollection(
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token) {
stream_.PostSetBufferCollection(id_, std::move(token));
}
void StreamImpl::Client::WatchBufferCollection(WatchBufferCollectionCallback callback) {
if (buffers_.Get(std::move(callback))) {
CloseConnection(ZX_ERR_BAD_STATE);
}
}
void StreamImpl::Client::GetNextFrame(GetNextFrameCallback callback) {
if (stream_.max_camping_buffers_ == 0) {
FX_LOGS(INFO) << Messages::kNoCampingBuffers;
}
if (frame_callback_) {
FX_PLOGS(INFO, ZX_ERR_BAD_STATE)
<< "Client called GetNextFrame while a previous call was still pending.";
CloseConnection(ZX_ERR_BAD_STATE);
return;
}
frame_callback_ = std::move(callback);
stream_.PostAddFrameSink(id_);
}
void StreamImpl::Client::Rebind(fidl::InterfaceRequest<Stream> request) {
request.Close(ZX_ERR_NOT_SUPPORTED);
CloseConnection(ZX_ERR_NOT_SUPPORTED);
}