blob: 64aaa230818f3a9b04e48e0bcd0619b170d57154 [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
29namespace camera3 {
30
31struct StreamInfo;
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -070032class Camera3OutputStream;
Zhijun He125684a2015-12-26 15:07:30 -080033
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 */
45class Camera3BufferManager: public virtual RefBase {
46public:
Mathias Agopian2752e5b2017-02-27 18:26:48 -080047 explicit Camera3BufferManager();
Zhijun He125684a2015-12-26 15:07:30 -080048
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 */
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -070085 status_t registerStream(wp<Camera3OutputStream>& stream, const StreamInfo &streamInfo);
Zhijun He125684a2015-12-26 15:07:30 -080086
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 */
Shuzhen Wang83bff122020-11-20 15:51:39 -0800102 status_t unregisterStream(int streamId, int streamSetId, bool isMultiRes);
Zhijun He125684a2015-12-26 15:07:30 -0800103
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 *
Yin-Chia Yehbf1b8b92019-03-06 14:56:08 -0800115 * Sometimes free buffers are discarded from consumer side and the dequeueBuffer call returns
116 * TIMED_OUT, in this case calling getBufferForStream again with noFreeBufferAtConsumer set to
117 * true will notify buffer manager to update its states and also tries to allocate a new buffer.
118 *
Zhijun He125684a2015-12-26 15:07:30 -0800119 * Return values:
120 *
121 * OK: Getting buffer for this stream was successful.
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -0700122 * ALREADY_EXISTS: Enough free buffers are already attached to this output buffer queue,
123 * user should just dequeue from the buffer queue.
Zhijun He125684a2015-12-26 15:07:30 -0800124 * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
125 * combination doesn't match what was registered, or this stream wasn't registered
126 * to this buffer manager before.
127 * NO_MEMORY: Unable to allocate a buffer for this stream at this time.
128 */
Yin-Chia Yehbf1b8b92019-03-06 14:56:08 -0800129 status_t getBufferForStream(
Shuzhen Wang83bff122020-11-20 15:51:39 -0800130 int streamId, int streamSetId, bool isMultiRes, sp<GraphicBuffer>* gb,
131 int* fenceFd, bool noFreeBufferAtConsumer = false);
Zhijun He125684a2015-12-26 15:07:30 -0800132
133 /**
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -0700134 * This method notifies the manager that a buffer has been released by the consumer.
135 *
136 * The buffer is not returned to the buffer manager, but is available for the stream the buffer
137 * is attached to for dequeuing.
138 *
139 * The notification lets the manager know how many buffers are directly available to the stream.
140 *
141 * If onBufferReleased is called for a given released buffer,
142 * returnBufferForStream may not be called for the same buffer, until the
143 * buffer has been reused. The manager will call detachBuffer on the stream
144 * if it needs the released buffer otherwise.
145 *
Yin-Chia Yeh89954d92017-05-21 17:28:53 -0700146 * When shouldFreeBuffer is set to true, caller must detach and free one buffer from the
147 * buffer queue, and then call notifyBufferRemoved to update the manager.
148 *
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -0700149 * Return values:
150 *
151 * OK: Buffer release was processed succesfully
152 * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
153 * combination doesn't match what was registered, or this stream wasn't registered
Yin-Chia Yeh89954d92017-05-21 17:28:53 -0700154 * to this buffer manager before, or shouldFreeBuffer is null/
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -0700155 */
Shuzhen Wang83bff122020-11-20 15:51:39 -0800156 status_t onBufferReleased(int streamId, int streamSetId, bool isMultiRes,
157 /*out*/bool* shouldFreeBuffer);
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -0700158
159 /**
Shuzhen Wangfd76cf52017-05-15 10:01:04 -0700160 * This method notifies the manager that certain buffers has been removed from the
161 * buffer queue by detachBuffer from the consumer.
Zhijun He125684a2015-12-26 15:07:30 -0800162 *
Shuzhen Wangfd76cf52017-05-15 10:01:04 -0700163 * The notification lets the manager update its internal handout buffer count and
164 * attached buffer counts accordingly. When buffers are detached from
165 * consumer, both handout and attached counts are decremented.
Zhijun He125684a2015-12-26 15:07:30 -0800166 *
Shuzhen Wangfd76cf52017-05-15 10:01:04 -0700167 * Return values:
Zhijun He125684a2015-12-26 15:07:30 -0800168 *
Shuzhen Wangfd76cf52017-05-15 10:01:04 -0700169 * OK: Buffer removal was processed succesfully
170 * BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
171 * combination doesn't match what was registered, or this stream wasn't registered
172 * to this buffer manager before, or the removed buffer count is larger than
173 * current total handoutCount or attachedCount.
Zhijun He125684a2015-12-26 15:07:30 -0800174 */
Shuzhen Wang83bff122020-11-20 15:51:39 -0800175 status_t onBuffersRemoved(int streamId, int streamSetId, bool isMultiRes, size_t count);
Zhijun He125684a2015-12-26 15:07:30 -0800176
177 /**
Yin-Chia Yeh89954d92017-05-21 17:28:53 -0700178 * This method notifiers the manager that a buffer is freed from the buffer queue, usually
179 * because onBufferReleased signals the caller to free a buffer via the shouldFreeBuffer flag.
180 */
Shuzhen Wang83bff122020-11-20 15:51:39 -0800181 void notifyBufferRemoved(int streamId, int streamSetId, bool isMultiRes);
Yin-Chia Yeh89954d92017-05-21 17:28:53 -0700182
183 /**
Zhijun He125684a2015-12-26 15:07:30 -0800184 * Dump the buffer manager statistics.
185 */
186 void dump(int fd, const Vector<String16> &args) const;
187
188private:
Yin-Chia Yeh89954d92017-05-21 17:28:53 -0700189 // allocatedBufferWaterMark will be decreased when:
190 // numAllocatedBuffersThisSet > numHandoutBuffersThisSet + BUFFER_WATERMARK_DEC_THRESHOLD
191 // This allows the watermark go back down after a burst of buffer requests
192 static const int BUFFER_WATERMARK_DEC_THRESHOLD = 3;
193
194 // onBufferReleased will set shouldFreeBuffer to true when:
195 // numAllocatedBuffersThisSet > allocatedBufferWaterMark AND
196 // numAllocatedBuffersThisStream > numHandoutBuffersThisStream + BUFFER_FREE_THRESHOLD
197 // So after a burst of buffer requests and back to steady state, the buffer queue should have
198 // (BUFFER_FREE_THRESHOLD + steady state handout buffer count) buffers.
199 static const int BUFFER_FREE_THRESHOLD = 3;
200
Zhijun He125684a2015-12-26 15:07:30 -0800201 /**
202 * Lock to synchronize the access to the methods of this class.
203 */
204 mutable Mutex mLock;
205
206 static const size_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
207
Zhijun He125684a2015-12-26 15:07:30 -0800208 struct GraphicBufferEntry {
209 sp<GraphicBuffer> graphicBuffer;
210 int fenceFd;
Chih-Hung Hsiehd19d9942016-08-29 14:21:14 -0700211 explicit GraphicBufferEntry(const sp<GraphicBuffer>& gb = 0, int fd = -1) :
Zhijun He125684a2015-12-26 15:07:30 -0800212 graphicBuffer(gb),
213 fenceFd(fd) {}
214 };
215
216 /**
217 * A buffer entry (indexed by stream ID) represents a single physically allocated buffer. For
218 * Gralloc V0, since each physical buffer is associated with one stream, this is
219 * a single entry map. For Gralloc V1, one physical buffer can be shared between different
220 * streams in one stream set, so this entry may include multiple entries, where the different
221 * graphic buffers have the same common Gralloc backing store.
222 */
223 typedef int StreamId;
224 typedef KeyedVector<StreamId, GraphicBufferEntry> BufferEntry;
225
226 typedef std::list<BufferEntry> BufferList;
227
228 /**
229 * Stream info map (indexed by stream ID) tracks all the streams registered to a particular
230 * stream set.
231 */
232 typedef KeyedVector<StreamId, StreamInfo> InfoMap;
233
234 /**
235 * Stream set buffer count map (indexed by stream ID) tracks all buffer counts of the streams
236 * registered to a particular stream set.
237 */
238 typedef KeyedVector<StreamId, size_t> BufferCountMap;
239
240 /**
241 * StreamSet keeps track of the stream info, free buffer list and hand-out buffer counts for
242 * each stream set.
243 */
244 struct StreamSet {
245 /**
246 * Stream set buffer count water mark representing the max number of allocated buffers
247 * (hand-out buffers + free buffers) count for each stream set. For a given stream set, when
248 * getBufferForStream() is called on this buffer manager, if the total allocated buffer
249 * count exceeds this water mark, the buffer manager will attempt to reduce it as follows:
250 *
251 * In getBufferForStream(), find a buffer associated with other streams (inside the same
252 * stream set) on the free buffer list and free it. For Gralloc V1, can just free the top
253 * of the free buffer list if the physical buffer sharing in this stream is supported.
254 *
255 * For a particular stream set, a larger allocatedBufferWaterMark increases the memory
256 * footprint of the stream set, but reduces the chance that getBufferForStream() will have
257 * to allocate a new buffer. We assume that the streams in one stream set are not streaming
258 * simultaneously, the max allocated buffer count water mark for a stream set will the max
259 * of all streams' total buffer counts. This will avoid new buffer allocation in steady
260 * streaming state.
Zhijun He8d1a1542016-01-29 20:28:21 -0800261 *
262 * This water mark can be dynamically changed, and will grow when the hand-out buffer count
263 * of each stream increases, until it reaches the maxAllowedBufferCount.
Zhijun He125684a2015-12-26 15:07:30 -0800264 */
265 size_t allocatedBufferWaterMark;
Zhijun He8d1a1542016-01-29 20:28:21 -0800266
267 /**
268 * The max allowed buffer count for this stream set. It is the max of total number of
269 * buffers for each stream. This is the upper bound of the allocatedBufferWaterMark.
270 */
271 size_t maxAllowedBufferCount;
272
Zhijun He125684a2015-12-26 15:07:30 -0800273 /**
274 * The stream info for all streams in this set
275 */
276 InfoMap streamInfoMap;
277 /**
Zhijun He125684a2015-12-26 15:07:30 -0800278 * The count of the buffers that were handed out to the streams of this set.
279 */
280 BufferCountMap handoutBufferCountMap;
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -0700281 /**
282 * The count of the buffers that are attached to the streams of this set.
283 * An attached buffer may be free or handed out
284 */
285 BufferCountMap attachedBufferCountMap;
286
Zhijun He125684a2015-12-26 15:07:30 -0800287 StreamSet() {
288 allocatedBufferWaterMark = 0;
Zhijun He8d1a1542016-01-29 20:28:21 -0800289 maxAllowedBufferCount = 0;
Zhijun He125684a2015-12-26 15:07:30 -0800290 }
291 };
292
293 /**
294 * Stream set map managed by this buffer manager.
295 */
Shuzhen Wang83bff122020-11-20 15:51:39 -0800296 struct StreamSetKey {
297 // The stream set ID
298 int id;
299 // Whether this stream set is for multi-resolution output streams. It's
300 // valid for 2 stream sets to have the same stream set ID if: one is for
301 // multi-resolution output stream, and the other one is not.
302 bool isMultiRes;
303
304 inline bool operator<(const StreamSetKey& other) const {
305 return (isMultiRes < other.isMultiRes) ||
306 ((isMultiRes == other.isMultiRes) && (id < other.id));
307 }
308 };
309 KeyedVector<StreamSetKey, StreamSet> mStreamSetMap;
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -0700310 KeyedVector<StreamId, wp<Camera3OutputStream>> mStreamMap;
Zhijun He125684a2015-12-26 15:07:30 -0800311
312 // TODO: There is no easy way to query the Gralloc version in this code yet, we have different
313 // code paths for different Gralloc versions, hardcode something here for now.
314 const uint32_t mGrallocVersion = GRALLOC_DEVICE_API_VERSION_0_1;
315
316 /**
317 * Check if this stream was successfully registered already. This method needs to be called with
318 * mLock held.
319 */
Shuzhen Wang83bff122020-11-20 15:51:39 -0800320 bool checkIfStreamRegisteredLocked(int streamId, StreamSetKey streamSetKey) const;
Zhijun He125684a2015-12-26 15:07:30 -0800321
Yin-Chia Yeh89954d92017-05-21 17:28:53 -0700322 /**
323 * Check if other streams in the stream set has extra buffer available to be freed, and
324 * free one if so.
325 */
Shuzhen Wang83bff122020-11-20 15:51:39 -0800326 status_t checkAndFreeBufferOnOtherStreamsLocked(int streamId, StreamSetKey streamSetKey);
Zhijun He125684a2015-12-26 15:07:30 -0800327};
328
329} // namespace camera3
330} // namespace android
331
332#endif // ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H