Home | History | Annotate | Download | only in device3
      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