1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Manage the producer and consumer buffers needed by FrameProviders. 19 */ 20 #pragma once 21 22 #include <Utils.h> 23 #include <linux/videodev2.h> 24 #include <condition_variable> 25 #include <map> 26 #include <mutex> 27 #include <queue> 28 #include <variant> 29 #include <vector> 30 31 namespace android { 32 namespace webcam { 33 34 enum BufferType { 35 V4L2 = 0, 36 }; 37 38 struct YuvHardwareBufferDesc { 39 uint8_t* yData = nullptr; 40 uint32_t yDataLength = 0; 41 uint32_t yRowStride = 0; 42 43 uint8_t* uData = nullptr; 44 uint32_t uDataLength = 0; 45 uint32_t uRowStride = 0; 46 47 uint8_t* vData = nullptr; 48 uint32_t vDataLength = 0; 49 uint32_t vRowStride = 0; 50 51 uint32_t uvPixelStride = 0; 52 }; 53 54 struct ARGBHardwareBufferDesc { 55 uint8_t *buf = nullptr; 56 uint32_t rowStride = 0; 57 }; 58 59 struct HardwareBufferDesc { 60 uint32_t width = 0; 61 uint32_t height = 0; 62 uint32_t format = 0; 63 uint32_t bufferId = 0; 64 std::variant<ARGBHardwareBufferDesc, YuvHardwareBufferDesc> bufferDesc; 65 }; 66 67 class BufferManager; 68 69 // Base class for Buffer, for future types apart from V4L2 70 // Thin wrapper over struct v4l2_buffer. The client should not free the memory obtained from 71 // getMem(). All Buffers are created by BufferManager through BufferCreatorAndDestroyer which is 72 // transport specific. 73 // TODO(b/267794640): Change Buffer to have either a std::shared_ptr to BufferManager or have 74 // BufferManager be a singleton. BufferManager should implement 75 // counting 'handout' buffers before freeing. BufferManager should explicitly 76 // check that there are no Buffers alive before freeing the handed out buffers. 77 // This will also ensure that the lifetime of BufferManager >= lifetime of 78 // Buffer. 79 class Buffer { 80 public: 81 Buffer() = default; 82 virtual BufferType getBufferType() = 0; 83 [[nodiscard]] virtual void* getMem() = 0; 84 [[nodiscard]] virtual size_t getLength() const = 0; 85 virtual void setBytesUsed(uint32_t bytesUsed) = 0; 86 virtual ~Buffer() = default; 87 setTimestamp(uint64_t ts)88 void setTimestamp(uint64_t ts) { mTimestamp = ts; } 89 getTimestamp()90 [[nodiscard]] uint64_t getTimestamp() const { return mTimestamp; } 91 [[nodiscard]] virtual uint32_t getIndex() const = 0; 92 93 friend class BufferManager; 94 95 private: 96 uint64_t mTimestamp = 0; 97 }; 98 99 class V4L2Buffer : public Buffer { 100 public: V4L2Buffer(void * mem,const struct v4l2_buffer * buffer)101 V4L2Buffer(void* mem, const struct v4l2_buffer* buffer) : mMem(mem), mBuffer(*buffer) {} V4L2Buffer()102 V4L2Buffer() { memset(&mBuffer, 0, sizeof(mBuffer)); } 103 ~V4L2Buffer() override = default; 104 getBufferType()105 BufferType getBufferType() override { return BufferType::V4L2; } 106 107 // Memory will be freed by BufferManager. Do not free. getMem()108 [[nodiscard]] void* getMem() override { return mMem; } 109 getLength()110 [[nodiscard]] size_t getLength() const override { return mBuffer.length; } 111 setBytesUsed(uint32_t bytesUsed)112 void setBytesUsed(uint32_t bytesUsed) override { mBuffer.bytesused = bytesUsed; } 113 getV4L2Buffer()114 struct v4l2_buffer* getV4L2Buffer() { 115 return &mBuffer; 116 } 117 getIndex()118 [[nodiscard]] uint32_t getIndex() const override { return mBuffer.index; } 119 120 private: 121 void* mMem = nullptr; 122 struct v4l2_buffer mBuffer {}; 123 }; 124 125 class BufferProducer { 126 public: 127 // Returns a free buffer if it is available. This method does not wait for a free 128 // buffer. Buffer is owned by BufferProducer. Caller should not manage the lifetime of the 129 // object and should ensure that all buffer references are dropped when BufferProducer goes out 130 // of scope. 131 virtual Buffer* getFreeBufferIfAvailable() = 0; 132 133 // Queues a filled buffer to the BufferManager. 134 virtual Status queueFilledBuffer(Buffer* buffer) = 0; 135 136 // Cancels a queued Buffer 137 virtual Status cancelBuffer(Buffer* buffer) = 0; 138 virtual ~BufferProducer() = default; 139 }; 140 141 class BufferConsumer { 142 public: 143 // Gets a filled buffer from BufferManager (waits if one is not available) and returns the 144 // consumer side buffer for the BufferManager to give away to the producer to use. 145 // Buffer is owned by BufferConsumer. Caller should not manage the lifetime of the object. 146 virtual Buffer* getFilledBufferAndSwap() = 0; 147 virtual ~BufferConsumer() = default; 148 }; 149 150 class BufferCreatorAndDestroyer { 151 public: 152 virtual ~BufferCreatorAndDestroyer() = default; 153 virtual Status allocateAndMapBuffers(std::shared_ptr<Buffer>* consumerBuffer, 154 std::vector<std::shared_ptr<Buffer>>* producerBuffer) = 0; 155 virtual void destroyBuffers(std::shared_ptr<Buffer>& consumerBuffer, 156 std::vector<std::shared_ptr<Buffer>>& producerBuffers) = 0; 157 }; 158 159 class BufferManager : public BufferConsumer, public BufferProducer { 160 // There are 2 types of buffers : the consumer side buffer and the producer side buffers. 161 // The consumer side needs only 1. 162 // The producer side is typically some component which fills in frames such as a FrameProvider 163 // class instance. 164 // The consumer side is typically some component that fetches filled buffers and sends them over 165 // some transport method to the host. 166 167 public: 168 // TODO(b/267794640): Look into better memory management 169 // BufferCreatorAndDestroyer is owned by the caller, it must be active throughout the lifetime 170 // of BufferManager 171 explicit BufferManager(BufferCreatorAndDestroyer* crD); 172 ~BufferManager() override; isInited()173 [[nodiscard]] bool isInited() const { return mInited; } 174 Buffer* getFreeBufferIfAvailable() override; 175 Status queueFilledBuffer(Buffer* buffer) override; 176 Status cancelBuffer(Buffer* buffer) override; 177 Buffer* getFilledBufferAndSwap() override; 178 179 private: 180 enum BufferState { 181 IN_USE = 0, 182 FILLED = 1, 183 FREE = 2, 184 }; 185 186 struct BufferItem { BufferItemBufferItem187 BufferItem() : buffer(nullptr), state(BufferState::FREE) {} BufferItemBufferItem188 BufferItem(std::shared_ptr<Buffer>& buf, BufferState st) : buffer(buf), state(st) {} 189 std::shared_ptr<Buffer> buffer; 190 BufferState state = BufferState::FREE; 191 }; 192 193 // Checks if a filled buffer has been made available by the producer and gets the vector index, 194 // of the latest filled buffer. Cancels buffers older than the one referenced by index. 195 bool filledProducerBufferAvailableLocked(uint32_t* index); 196 bool changeProducerBufferStateLocked(Buffer* buffer, BufferState newState); 197 198 bool mInited = false; 199 BufferCreatorAndDestroyer* mCrD = nullptr; 200 201 std::mutex mBufferLock; // guards all operations relating to Buffer and BufferItems 202 std::condition_variable mProducerBufferFilled; // guarded by mBufferLock 203 BufferItem mConsumerBufferItem; // guarded by mBufferLock 204 // Using a simple vector here as we don't expect to have more than 3-4 buffers in circulation 205 // We have multiple producer buffers so that skews between other producers being used by the 206 // producer side - eg: buffer from camera doesn't get blocked from getting encoded while 207 // consumer is still consuming the consumer side buffer (this could happen if we had only 1 208 // producer buffer and 1 consumer buffer and there's a skew between camera frame production and 209 // consumer (UVC gadget driver etc) frame consumption. 210 std::vector<BufferItem> mProducerBufferItems; // guarded by mBufferLock 211 }; 212 213 } // namespace webcam 214 } // namespace android 215