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