blob: da3508f342c0457ce03a4d8c4b7c030e5b707c45 [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.
#ifndef SRC_CAMERA_BIN_DEVICE_STREAM_IMPL_H_
#define SRC_CAMERA_BIN_DEVICE_STREAM_IMPL_H_
#include <fuchsia/camera2/cpp/fidl.h>
#include <fuchsia/camera3/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/wait.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fit/result.h>
#include <zircon/status.h>
#include <memory>
#include <queue>
#include <vector>
// Represents a specific stream in a camera device's configuration. Serves multiple clients of the
// camera3.Stream protocol.
class StreamImpl {
public:
StreamImpl(fidl::InterfaceHandle<fuchsia::camera2::Stream> legacy_stream,
fidl::InterfaceRequest<fuchsia::camera3::Stream> request, uint32_t max_camping_buffers,
fit::closure on_no_clients);
~StreamImpl();
private:
// Called if the underlying legacy stream disconnects.
void OnLegacyStreamDisconnected(zx_status_t status);
// Posts a task to remove the client with the given id.
void PostRemoveClient(uint64_t id);
// Posts a task to add the client with the given id to the queue of frame recipients.
void PostAddFrameSink(uint64_t id);
// Called when the legacy stream's OnFrameAvailable event fires.
void OnFrameAvailable(fuchsia::camera2::FrameAvailableInfo info);
// Sends pending frames to waiting recipients.
void SendFrames();
// Represents a single client connection to the StreamImpl class.
class Client : public fuchsia::camera3::Stream {
public:
Client(StreamImpl& stream, uint64_t id,
fidl::InterfaceRequest<fuchsia::camera3::Stream> request);
~Client();
// Posts a task to transfer ownership of the given frame to this client.
void PostSendFrame(fuchsia::camera3::FrameInfo frame);
private:
// Closes |binding_| with the provided |status| epitaph, and removes the client instance from
// the parent |clients_| map.
void CloseConnection(zx_status_t status);
// Called when the client endpoint of |binding_| is closed.
void OnClientDisconnected(zx_status_t status);
// |fuchsia::camera3::Stream|
void SetCropRegion(std::unique_ptr<fuchsia::math::RectF> region) override;
void WatchCropRegion(WatchCropRegionCallback callback) override;
void SetResolution(uint32_t index) override;
void WatchResolution(WatchResolutionCallback callback) override;
void GetNextFrame(GetNextFrameCallback callback) override;
void Rebind(fidl::InterfaceRequest<Stream> request) override;
StreamImpl& stream_;
uint64_t id_;
async::Loop loop_;
fidl::Binding<fuchsia::camera3::Stream> binding_;
GetNextFrameCallback frame_callback_;
};
async::Loop loop_;
fuchsia::camera2::StreamPtr legacy_stream_;
std::map<uint64_t, std::unique_ptr<Client>> clients_;
uint64_t client_id_next_ = 1;
fit::closure on_no_clients_;
uint32_t max_camping_buffers_;
uint64_t frame_counter_ = 0;
std::queue<uint64_t> frame_sinks_;
bool frame_sink_warning_sent_ = false;
std::queue<fuchsia::camera3::FrameInfo> frames_;
std::map<uint32_t, std::unique_ptr<async::Wait>> frame_waiters_;
friend class Client;
};
#endif // SRC_CAMERA_BIN_DEVICE_STREAM_IMPL_H_