1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_ 2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_ 3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <gui/BufferQueueDefs.h> 5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h> 71db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka#include <pdx/status.h> 8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/buffer_hub_client.h> 952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include <private/dvr/bufferhub_rpc.h> 10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/epoll_file_descriptor.h> 11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/ring_buffer.h> 12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <memory> 1452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include <queue> 15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <vector> 16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android { 18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr { 19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ConsumerQueue; 21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// |BufferHubQueue| manages a queue of |BufferHubBuffer|s. Buffers are 23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// automatically re-requeued when released by the remote side. 24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferHubQueue : public pdx::Client { 25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public: 260b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai using BufferAvailableCallback = std::function<void()>; 270b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai using BufferRemovedCallback = 280b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai std::function<void(const std::shared_ptr<BufferHubBuffer>&)>; 290b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai 30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko virtual ~BufferHubQueue() {} 31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 32b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Creates a new consumer queue that is attached to the producer. Returns 33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // a new consumer queue client or nullptr on failure. 34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::unique_ptr<ConsumerQueue> CreateConsumerQueue(); 35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 36b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Creates a new consumer queue that is attached to the producer. This queue 378a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // sets each of its imported consumer buffers to the ignored state to avoid 388a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // participation in lifecycle events. 398a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue(); 408a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka 416bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // Returns whether the buffer queue is in async mode. 426bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai bool is_async() const { return is_async_; } 436bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai 44b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Returns the default buffer width of this buffer queue. 456bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai uint32_t default_width() const { return default_width_; } 461601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai 47b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Returns the default buffer height of this buffer queue. 486bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai uint32_t default_height() const { return default_height_; } 491601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai 50b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Returns the default buffer format of this buffer queue. 516bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai uint32_t default_format() const { return default_format_; } 521601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai 53b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Creates a new consumer in handle form for immediate transport over RPC. 5452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle( 5552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka bool silent = false); 561db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka 57b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Returns the number of buffers avaiable for dequeue. 5852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka size_t count() const { return available_buffers_.size(); } 59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 60b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Returns the total number of buffers that the queue is tracking. 61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko size_t capacity() const { return capacity_; } 62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 63b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Returns the size of metadata structure associated with this queue. 6452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka size_t metadata_size() const { return user_metadata_size_; } 65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 66b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Returns whether the buffer queue is full. 6752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka bool is_full() const { 6852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka return available_buffers_.size() >= kMaxQueueCapacity; 6952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka } 70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko explicit operator bool() const { return epoll_fd_.IsValid(); } 72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 73638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai int GetBufferId(size_t slot) const { 74638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id() 75638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai : -1; 76638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai } 77638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai 78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const { 79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return buffers_[slot]; 80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 82b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<int> GetEventMask(int events) { 83dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai if (auto* client_channel = GetChannel()) { 84dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai return client_channel->GetEventMask(events); 85dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai } else { 86dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai return pdx::ErrorStatus(EINVAL); 87dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai } 88dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai } 89dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai 908a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // Returns an fd that signals pending queue events using 918a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // EPOLLIN/POLLIN/readible. Either HandleQueueEvents or WaitForBuffers may be 928a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // called to handle pending queue events. 938a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka int queue_fd() const { return epoll_fd_.Get(); } 948a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka 958a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // Handles any pending events, returning available buffers to the queue and 968a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // reaping disconnected buffers. Returns true if successful, false if an error 978a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // occurred. 988a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka bool HandleQueueEvents() { return WaitForBuffers(0); } 998a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka 1000b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai // Set buffer event callbacks, which are std::function wrappers. The caller is 1010b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai // responsible for ensuring the validity of these callbacks' callable targets. 1020b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai void SetBufferAvailableCallback(BufferAvailableCallback callback); 1030b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai void SetBufferRemovedCallback(BufferRemovedCallback callback); 1040b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai 105b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // The queue tracks at most this many buffers. 106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko static constexpr size_t kMaxQueueCapacity = 107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko android::BufferQueueDefs::NUM_BUFFER_SLOTS; 108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko static constexpr int kNoTimeOut = -1; 110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 1111db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka int id() const { return id_; } 1128a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka bool hung_up() const { return hung_up_; } 1131db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka 114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko protected: 115b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka BufferHubQueue(pdx::LocalChannelHandle channel); 1161db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka BufferHubQueue(const std::string& endpoint_path); 1171db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka 1181db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka // Imports the queue parameters by querying BufferHub for the parameters for 1191db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka // this channel. 120b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> ImportQueue(); 1211db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka 1221db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka // Sets up the queue with the given parameters. 1236bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai void SetupQueue(const QueueInfo& queue_info); 124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 125b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Register a buffer for management by the queue. Used by subclasses to add a 126b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // buffer to internal bookkeeping. 127b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer, 128b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka size_t slot); 129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 130bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai // Called by ProducerQueue::RemoveBuffer and ConsumerQueue::RemoveBuffer only 131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // to deregister a buffer for epoll and internal bookkeeping. 132bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai virtual pdx::Status<void> RemoveBuffer(size_t slot); 133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 134005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai // Free all buffers that belongs to this queue. Can only be called from 135005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai // producer side. 136005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai virtual pdx::Status<void> FreeAllBuffers(); 137005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai 138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Dequeue a buffer from the free queue, blocking until one is available. The 139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // timeout argument specifies the number of milliseconds that |Dequeue()| will 140b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely, 141b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // while specifying a timeout equal to zero cause Dequeue() to return 142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // immediately, even if no buffers are available. 14352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout, 14452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka size_t* slot); 145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 146b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Waits for buffers to become available and adds them to the available queue. 147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko bool WaitForBuffers(int timeout); 148dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai 149b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> HandleBufferEvent(size_t slot, int event_fd, 150b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka int poll_events); 151b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> HandleQueueEvent(int poll_events); 152b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 153b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Entry in the ring buffer of available buffers that stores related 154b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // per-buffer data. 155b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka struct Entry { 156b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka Entry() : slot(0) {} 15752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot, 15852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka uint64_t index) 15952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka : buffer(buffer), slot(slot), index(index) {} 160b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka Entry(const std::shared_ptr<BufferHubBuffer>& buffer, 161b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence, 162b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka size_t slot) 163b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka : buffer(buffer), 164b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka metadata(std::move(metadata)), 165b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka fence(std::move(fence)), 166b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka slot(slot) {} 167b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka Entry(Entry&&) = default; 168b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka Entry& operator=(Entry&&) = default; 169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 170b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka std::shared_ptr<BufferHubBuffer> buffer; 171b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka std::unique_ptr<uint8_t[]> metadata; 172b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::LocalHandle fence; 173b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka size_t slot; 17452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka uint64_t index; 17552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka }; 17652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka 17752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka struct EntryComparator { 17852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka bool operator()(const Entry& lhs, const Entry& rhs) { 17952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka return lhs.index > rhs.index; 18052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka } 181b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka }; 182b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 183b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Enqueues a buffer to the available list (Gained for producer or Acquireed 184b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // for consumer). 185b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> Enqueue(Entry entry); 186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 187b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Called when a buffer is allocated remotely. 188b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka virtual pdx::Status<void> OnBufferAllocated() { return {}; } 189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 190b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Size of the metadata that buffers in this queue cary. 19152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka size_t user_metadata_size_{0}; 192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private: 194b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka void Initialize(); 195b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 196b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Special epoll data field indicating that the epoll event refers to the 197b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // queue. 198b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka static constexpr int64_t kEpollQueueEventIndex = -1; 199b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko static constexpr size_t kMaxEvents = 128; 201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 202b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // The u64 data field of an epoll event is interpreted as int64_t: 203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // When |index| >= 0 and |index| < kMaxQueueCapacity it refers to a specific 204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // element of |buffers_| as a direct index; 205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko static bool is_buffer_event_index(int64_t index) { 206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return index >= 0 && 207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko index < static_cast<int64_t>(BufferHubQueue::kMaxQueueCapacity); 208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 210b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // When |index| == kEpollQueueEventIndex it refers to the queue itself. 211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko static bool is_queue_event_index(int64_t index) { 212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return index == BufferHubQueue::kEpollQueueEventIndex; 213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 2156bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // Whether the buffer queue is operating in Async mode. 2166bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // From GVR's perspective of view, this means a buffer can be acquired 2176bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // asynchronously by the compositor. 2186bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // From Android Surface's perspective of view, this is equivalent to 2196bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // IGraphicBufferProducer's async mode. When in async mode, a producer 2206bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // will never block even if consumer is running slow. 2216bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai bool is_async_{false}; 2226bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai 2236bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // Default buffer width that is set during ProducerQueue's creation. 2241601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai size_t default_width_{1}; 2251601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai 2266bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // Default buffer height that is set during ProducerQueue's creation. 2271601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai size_t default_height_{1}; 2281601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai 2296bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai // Default buffer format that is set during ProducerQueue's creation. 2306bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai int32_t default_format_{1}; // PIXEL_FORMAT_RGBA_8888 2311601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai 232b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Tracks the buffers belonging to this queue. Buffers are stored according to 233b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // "slot" in this vector. Each slot is a logical id of the buffer within this 234b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // queue regardless of its queue position or presence in the ring buffer. 235638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_; 236b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 237b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Buffers and related data that are available for dequeue. 23852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka // RingBuffer<Entry> available_buffers_{kMaxQueueCapacity}; 23952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka std::priority_queue<Entry, std::vector<Entry>, EntryComparator> 24052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka available_buffers_; 241b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 242b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Keeps track with how many buffers have been added into the queue. 243b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka size_t capacity_{0}; 244b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 245b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Epoll fd used to manage buffer events. 246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko EpollFileDescriptor epoll_fd_; 247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 2488a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // Flag indicating that the other side hung up. For ProducerQueues this 2498a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // triggers when BufferHub dies or explicitly closes the queue channel. For 2508a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // ConsumerQueues this can either mean the same or that the ProducerQueue on 2518a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // the other end hung up. 2528a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka bool hung_up_{false}; 2538a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka 2541db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka // Global id for the queue that is consistent across processes. 255b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka int id_{-1}; 2561db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka 2570b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai // Buffer event callbacks 2580b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai BufferAvailableCallback on_buffer_available_; 2590b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai BufferRemovedCallback on_buffer_removed_; 2600b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai 261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko BufferHubQueue(const BufferHubQueue&) = delete; 262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko void operator=(BufferHubQueue&) = delete; 263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}; 264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> { 266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public: 267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits 268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // in |usage_clear_mask| will be automatically masked off. Note that 269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // |usage_set_mask| and |usage_clear_mask| may conflict with each other, but 270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // |usage_set_mask| takes precedence over |usage_clear_mask|. All buffer 271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // allocation through this producer queue shall not have any of the usage bits 272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // in |usage_deny_set_mask| set. Allocation calls violating this will be 273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // rejected. All buffer allocation through this producer queue must have all 274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // the usage bits in |usage_deny_clear_mask| set. Allocation calls violating 275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // this will be rejected. Note that |usage_deny_set_mask| and 276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // |usage_deny_clear_mask| shall not conflict with each other. Such 277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // configuration will be treated as invalid input on creation. 2786bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai static std::unique_ptr<ProducerQueue> Create( 2796bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai const ProducerQueueConfig& config, const UsagePolicy& usage) { 2806bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai return BASE::Create(config, usage); 2812b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka } 282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 283b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Import a ProducerQueue from a channel handle. 284b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka static std::unique_ptr<ProducerQueue> Import(pdx::LocalChannelHandle handle) { 2851db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka return BASE::Create(std::move(handle)); 286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Get a buffer producer. Note that the method doesn't check whether the 289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // buffer slot has a valid buffer that has been allocated already. When no 290b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // buffer has been imported before it returns nullptr; otherwise it returns 291b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // a shared pointer to a BufferProducer. 292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const { 293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return std::static_pointer_cast<BufferProducer>( 294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko BufferHubQueue::GetBuffer(slot)); 295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 2978fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai // Batch allocate buffers. Once allocated, producer buffers are automatically 2988fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai // enqueue'd into the ProducerQueue and available to use (i.e. in GAINED 2998fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai // state). Upon success, returns a list of slots for each buffer allocated. 3008fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai pdx::Status<std::vector<size_t>> AllocateBuffers( 3018fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format, 3028fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai uint64_t usage, size_t buffer_count); 3038fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai 304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Allocate producer buffer to populate the queue. Once allocated, a producer 305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // buffer is automatically enqueue'd into the ProducerQueue and available to 3068fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai // use (i.e. in GAINED state). Upon success, returns the slot number for the 3078fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai // buffer allocated. 3088fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai pdx::Status<size_t> AllocateBuffer(uint32_t width, uint32_t height, 3098fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai uint32_t layer_count, uint32_t format, 3108fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai uint64_t usage); 311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Add a producer buffer to populate the queue. Once added, a producer buffer 313b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // is available to use (i.e. in GAINED state). 314b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer, 315b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka size_t slot); 316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 317bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai // Remove producer buffer from the queue. 318bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai pdx::Status<void> RemoveBuffer(size_t slot) override; 319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 320005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai // Free all buffers on this producer queue. 321005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai pdx::Status<void> FreeAllBuffers() override { 322005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai return BufferHubQueue::FreeAllBuffers(); 323005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai } 324005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai 325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode, 326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // and caller should call Post() once it's done writing to release the buffer 327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // to the consumer side. 3289d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka pdx::Status<std::shared_ptr<BufferProducer>> Dequeue( 329b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka int timeout, size_t* slot, pdx::LocalHandle* release_fence); 33052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka pdx::Status<std::shared_ptr<BufferProducer>> Dequeue( 33152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta, 33252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka pdx::LocalHandle* release_fence); 333b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka 334b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka // Enqueues a producer buffer in the queue. 335b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer, 33652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka size_t slot, uint64_t index) { 33752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka return BufferHubQueue::Enqueue({buffer, slot, index}); 338b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka } 339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private: 341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko friend BASE; 342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Constructors are automatically exposed through ProducerQueue::Create(...) 344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // static template methods inherited from ClientBase, which take the same 345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // arguments as the constructors. 346b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka explicit ProducerQueue(pdx::LocalChannelHandle handle); 3476bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage); 348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}; 349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 3501db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabakaclass ConsumerQueue : public BufferHubQueue { 351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public: 352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Get a buffer consumer. Note that the method doesn't check whether the 353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // buffer slot has a valid buffer that has been imported already. When no 3548a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // buffer has been imported before it returns nullptr; otherwise returns a 3558a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // shared pointer to a BufferConsumer. 356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const { 357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return std::static_pointer_cast<BufferConsumer>( 358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko BufferHubQueue::GetBuffer(slot)); 359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 3618a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // Import a ConsumerQueue from a channel handle. |ignore_on_import| controls 3628a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // whether or not buffers are set to be ignored when imported. This may be 3638a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // used to avoid participation in the buffer lifecycle by a consumer queue 3648a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // that is only used to spawn other consumer queues, such as in an 3658a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka // intermediate service. 36652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle) { 3678a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka return std::unique_ptr<ConsumerQueue>( 36852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka new ConsumerQueue(std::move(handle))); 3691db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka } 3701db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka 371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Import newly created buffers from the service side. 3721db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka // Returns number of buffers successfully imported or an error. 373b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<size_t> ImportBuffers(); 374e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed 376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // mode, and caller should call Releasse() once it's done writing to release 377e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // the buffer to the producer side. |meta| is passed along from BufferHub, 378e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // The user of BufferProducer is responsible with making sure that the 379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Dequeue() is done with the corect metadata type and size with those used 380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // when the buffer is orignally created. 381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko template <typename Meta> 3829d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue( 383b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) { 384ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence); 385e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 3869d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue( 387b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) { 3888a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka return Dequeue(timeout, slot, nullptr, 0, acquire_fence); 3898a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka } 390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 3919d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue( 39252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka int timeout, size_t* slot, void* meta, size_t user_metadata_size, 39352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka pdx::LocalHandle* acquire_fence); 39452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue( 39552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta, 396b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::LocalHandle* acquire_fence); 3971db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka 398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private: 3991db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka friend BufferHubQueue; 400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 40152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka ConsumerQueue(pdx::LocalChannelHandle handle); 402e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 403e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Add a consumer buffer to populate the queue. Once added, a consumer buffer 404e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // is NOT available to use until the producer side |Post| it. |WaitForBuffers| 405e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // will catch the |Post| and |Acquire| the buffer to make it available for 406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // consumer. 407b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer, 408b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka size_t slot); 409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 410b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka pdx::Status<void> OnBufferAllocated() override; 411e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}; 412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace dvr 414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace android 415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_ 417