1 /* 2 * Copyright 2016 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 #ifndef ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H 18 #define ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H 19 20 #include <list> 21 #include <algorithm> 22 #include <ui/GraphicBuffer.h> 23 #include <utils/RefBase.h> 24 #include <utils/KeyedVector.h> 25 #include "Camera3OutputStream.h" 26 27 namespace android { 28 29 namespace camera3 { 30 31 struct StreamInfo; 32 class Camera3OutputStream; 33 34 /** 35 * A class managing the graphic buffers that is used by camera output streams. It allocates and 36 * hands out Gralloc buffers to the clients (e.g., Camera3OutputStream) based on the requests. 37 * When clients request a buffer, buffer manager will pick a buffer if there are some already 38 * allocated buffer available, will allocate a buffer otherwise. When there are too many allocated 39 * buffer maintained by the buffer manager, it will dynamically deallocate some buffers that are 40 * solely owned by this buffer manager. 41 * In doing so, it reduces the memory footprint unless it is already minimal without impacting 42 * performance. 43 * 44 */ 45 class Camera3BufferManager: public virtual RefBase { 46 public: 47 Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator = NULL); 48 49 virtual ~Camera3BufferManager(); 50 51 /** 52 * This method registers an output stream to this buffer manager by using the provided stream 53 * information. 54 * 55 * The stream info includes the necessary information such as stream size, format, buffer count, 56 * usage flags, etc. for the buffer manager to allocate and hand out buffers for this stream. 57 * 58 * It's illegal to call this method if the stream is not CONFIGURED yet, as some critical 59 * stream properties (e.g., combined usage flags) are only available in this state. It is also 60 * illegal to call this method with an invalid stream set ID (CAMERA3_STREAM_SET_ID_INVALID), 61 * as the invalid stream set ID indicates that this stream doesn't intend to use buffer manager. 62 * 63 * 64 * Once a stream is successfully registered to this buffer manager, the buffer manager takes 65 * over the buffer allocation role and provides buffers to this stream via getBufferForStream(). 66 * The returned buffer can be sent to the camera HAL for image output, and then queued to the 67 * ANativeWindow (Surface) for downstream consumer to acquire. Once the image buffer is released 68 * by the consumer end point, the BufferQueueProducer callback onBufferReleased will call 69 * returnBufferForStream() to return the free buffer to this buffer manager. If the stream 70 * uses buffer manager to manage the stream buffers, it should disable the BufferQueue 71 * allocation via IGraphicBufferProducer::allowAllocation(false). 72 * 73 * Registering an already registered stream has no effect. 74 * 75 * Return values: 76 * 77 * OK: Registration of the new stream was successful. 78 * BAD_VALUE: This stream is not at CONFIGURED state, or the stream ID or stream set 79 * ID are invalid, or attempting to register the same stream to multiple 80 * stream sets, or other stream properties are invalid. 81 * INVALID_OPERATION: This buffer manager doesn't support buffer sharing across this stream 82 * and other streams that were already registered with the same stream set 83 * ID. 84 */ 85 status_t registerStream(wp<Camera3OutputStream>& stream, const StreamInfo &streamInfo); 86 87 /** 88 * This method unregisters a stream from this buffer manager. 89 * 90 * After a stream is unregistered, further getBufferForStream() calls will fail for this stream. 91 * After all streams for a given stream set are unregistered, all the buffers solely owned (for 92 * this stream set) by this buffer manager will be freed; all buffers subsequently returned to 93 * this buffer manager for this stream set will be freed immediately. 94 * 95 * Return values: 96 * 97 * OK: Removal of the a stream from this buffer manager was successful. 98 * BAD_VALUE: stream ID or stream set ID are invalid, or stream ID and stream set ID 99 * combination doesn't match what was registered, or this stream wasn't registered 100 * to this buffer manager before. 101 */ 102 status_t unregisterStream(int streamId, int streamSetId); 103 104 /** 105 * This method obtains a buffer for a stream from this buffer manager. 106 * 107 * This method returns the first free buffer from the free buffer list (associated with this 108 * stream set) if there is any. Otherwise, it will allocate a buffer for this stream, return 109 * it and increment its count of handed-out buffers. When the total number of allocated buffers 110 * is too high, it may deallocate the unused buffers to save memory footprint of this stream 111 * set. 112 * 113 * After this call, the client takes over the ownership of this buffer if it is not freed. 114 * 115 * Return values: 116 * 117 * OK: Getting buffer for this stream was successful. 118 * ALREADY_EXISTS: Enough free buffers are already attached to this output buffer queue, 119 * user should just dequeue from the buffer queue. 120 * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID 121 * combination doesn't match what was registered, or this stream wasn't registered 122 * to this buffer manager before. 123 * NO_MEMORY: Unable to allocate a buffer for this stream at this time. 124 */ 125 status_t getBufferForStream(int streamId, int streamSetId, sp<GraphicBuffer>* gb, int* fenceFd); 126 127 /** 128 * This method notifies the manager that a buffer has been released by the consumer. 129 * 130 * The buffer is not returned to the buffer manager, but is available for the stream the buffer 131 * is attached to for dequeuing. 132 * 133 * The notification lets the manager know how many buffers are directly available to the stream. 134 * 135 * If onBufferReleased is called for a given released buffer, 136 * returnBufferForStream may not be called for the same buffer, until the 137 * buffer has been reused. The manager will call detachBuffer on the stream 138 * if it needs the released buffer otherwise. 139 * 140 * Return values: 141 * 142 * OK: Buffer release was processed succesfully 143 * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID 144 * combination doesn't match what was registered, or this stream wasn't registered 145 * to this buffer manager before. 146 */ 147 status_t onBufferReleased(int streamId, int streamSetId); 148 149 /** 150 * This method returns a buffer for a stream to this buffer manager. 151 * 152 * When a buffer is returned, it is treated as a free buffer and may either be reused for future 153 * getBufferForStream() calls, or freed if there total number of outstanding allocated buffers 154 * is too large. The latter only applies to the case where the buffer are physically shared 155 * between streams in the same stream set. A physically shared buffer is the buffer that has one 156 * physical back store but multiple handles. Multiple stream can access the same physical memory 157 * with their own handles. Physically shared buffer can only be supported by Gralloc HAL V1. 158 * See hardware/libhardware/include/hardware/gralloc1.h for more details. 159 * 160 * 161 * This call takes the ownership of the returned buffer if it was allocated by this buffer 162 * manager; clients should not use this buffer after this call. Attempting to access this buffer 163 * after this call will have undefined behavior. Holding a reference to this buffer after this 164 * call may cause memory leakage. If a BufferQueue is used to track the buffers handed out by 165 * this buffer queue, it is recommended to call detachNextBuffer() from the buffer queue after 166 * BufferQueueProducer onBufferReleased callback is fired, and return it to this buffer manager. 167 * 168 * OK: Buffer return for this stream was successful. 169 * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID combination 170 * doesn't match what was registered, or this stream wasn't registered to this 171 * buffer manager before. 172 */ 173 status_t returnBufferForStream(int streamId, int streamSetId, const sp<GraphicBuffer>& buffer, 174 int fenceFd); 175 176 /** 177 * Dump the buffer manager statistics. 178 */ 179 void dump(int fd, const Vector<String16> &args) const; 180 181 private: 182 /** 183 * Lock to synchronize the access to the methods of this class. 184 */ 185 mutable Mutex mLock; 186 187 static const size_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS; 188 189 /** 190 * mAllocator is the connection to SurfaceFlinger that is used to allocate new GraphicBuffer 191 * objects. 192 */ 193 sp<IGraphicBufferAlloc> mAllocator; 194 195 struct GraphicBufferEntry { 196 sp<GraphicBuffer> graphicBuffer; 197 int fenceFd; 198 GraphicBufferEntry(const sp<GraphicBuffer>& gb = 0, int fd = -1) : 199 graphicBuffer(gb), 200 fenceFd(fd) {} 201 }; 202 203 /** 204 * A buffer entry (indexed by stream ID) represents a single physically allocated buffer. For 205 * Gralloc V0, since each physical buffer is associated with one stream, this is 206 * a single entry map. For Gralloc V1, one physical buffer can be shared between different 207 * streams in one stream set, so this entry may include multiple entries, where the different 208 * graphic buffers have the same common Gralloc backing store. 209 */ 210 typedef int StreamId; 211 typedef KeyedVector<StreamId, GraphicBufferEntry> BufferEntry; 212 213 typedef std::list<BufferEntry> BufferList; 214 215 /** 216 * Stream info map (indexed by stream ID) tracks all the streams registered to a particular 217 * stream set. 218 */ 219 typedef KeyedVector<StreamId, StreamInfo> InfoMap; 220 221 /** 222 * Stream set buffer count map (indexed by stream ID) tracks all buffer counts of the streams 223 * registered to a particular stream set. 224 */ 225 typedef KeyedVector<StreamId, size_t> BufferCountMap; 226 227 /** 228 * StreamSet keeps track of the stream info, free buffer list and hand-out buffer counts for 229 * each stream set. 230 */ 231 struct StreamSet { 232 /** 233 * Stream set buffer count water mark representing the max number of allocated buffers 234 * (hand-out buffers + free buffers) count for each stream set. For a given stream set, when 235 * getBufferForStream() is called on this buffer manager, if the total allocated buffer 236 * count exceeds this water mark, the buffer manager will attempt to reduce it as follows: 237 * 238 * In getBufferForStream(), find a buffer associated with other streams (inside the same 239 * stream set) on the free buffer list and free it. For Gralloc V1, can just free the top 240 * of the free buffer list if the physical buffer sharing in this stream is supported. 241 * 242 * For a particular stream set, a larger allocatedBufferWaterMark increases the memory 243 * footprint of the stream set, but reduces the chance that getBufferForStream() will have 244 * to allocate a new buffer. We assume that the streams in one stream set are not streaming 245 * simultaneously, the max allocated buffer count water mark for a stream set will the max 246 * of all streams' total buffer counts. This will avoid new buffer allocation in steady 247 * streaming state. 248 * 249 * This water mark can be dynamically changed, and will grow when the hand-out buffer count 250 * of each stream increases, until it reaches the maxAllowedBufferCount. 251 */ 252 size_t allocatedBufferWaterMark; 253 254 /** 255 * The max allowed buffer count for this stream set. It is the max of total number of 256 * buffers for each stream. This is the upper bound of the allocatedBufferWaterMark. 257 */ 258 size_t maxAllowedBufferCount; 259 260 /** 261 * The stream info for all streams in this set 262 */ 263 InfoMap streamInfoMap; 264 /** 265 * The free buffer list for all the buffers belong to this set. The free buffers are 266 * returned by the returnBufferForStream() call, and available for reuse. 267 */ 268 BufferList freeBuffers; 269 /** 270 * The count of the buffers that were handed out to the streams of this set. 271 */ 272 BufferCountMap handoutBufferCountMap; 273 /** 274 * The count of the buffers that are attached to the streams of this set. 275 * An attached buffer may be free or handed out 276 */ 277 BufferCountMap attachedBufferCountMap; 278 279 StreamSet() { 280 allocatedBufferWaterMark = 0; 281 maxAllowedBufferCount = 0; 282 } 283 }; 284 285 /** 286 * Stream set map managed by this buffer manager. 287 */ 288 typedef int StreamSetId; 289 KeyedVector<StreamSetId, StreamSet> mStreamSetMap; 290 KeyedVector<StreamId, wp<Camera3OutputStream>> mStreamMap; 291 292 // TODO: There is no easy way to query the Gralloc version in this code yet, we have different 293 // code paths for different Gralloc versions, hardcode something here for now. 294 const uint32_t mGrallocVersion = GRALLOC_DEVICE_API_VERSION_0_1; 295 296 /** 297 * Check if this stream was successfully registered already. This method needs to be called with 298 * mLock held. 299 */ 300 bool checkIfStreamRegisteredLocked(int streamId, int streamSetId) const; 301 302 /** 303 * Add a buffer entry to the BufferList. This method needs to be called with mLock held. 304 */ 305 status_t addBufferToBufferListLocked(BufferList &bufList, const BufferEntry &buffer); 306 307 /** 308 * Remove all buffers from the BufferList. 309 * 310 * Note that this doesn't mean that the buffers are freed after this call. A buffer is freed 311 * only if all other references to it are dropped. 312 * 313 * This method needs to be called with mLock held. 314 */ 315 status_t removeBuffersFromBufferListLocked(BufferList &bufList, int streamId); 316 317 /** 318 * Get the first available buffer from the buffer list for this stream. The graphicBuffer inside 319 * this entry will be NULL if there is no any GraphicBufferEntry found. After this call, the 320 * GraphicBufferEntry will be removed from the BufferList if a GraphicBufferEntry is found. 321 * 322 * This method needs to be called with mLock held. 323 * 324 */ 325 GraphicBufferEntry getFirstBufferFromBufferListLocked(BufferList& buffers, int streamId); 326 327 /** 328 * Check if there is any buffer associated with this stream in the given buffer list. 329 * 330 * This method needs to be called with mLock held. 331 * 332 */ 333 bool inline hasBufferForStreamLocked(BufferList& buffers, int streamId); 334 }; 335 336 } // namespace camera3 337 } // namespace android 338 339 #endif // ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H 340