Home | History | Annotate | Download | only in device3
      1 /*
      2  * Copyright 2014,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_STREAMSPLITTER_H
     18 #define ANDROID_SERVERS_STREAMSPLITTER_H
     19 
     20 #include <unordered_set>
     21 
     22 #include <gui/IConsumerListener.h>
     23 #include <gui/IProducerListener.h>
     24 #include <gui/BufferItemConsumer.h>
     25 
     26 #include <utils/Condition.h>
     27 #include <utils/Mutex.h>
     28 #include <utils/StrongPointer.h>
     29 #include <utils/Timers.h>
     30 
     31 #define SP_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
     32 #define SP_LOGI(x, ...) ALOGI("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
     33 #define SP_LOGW(x, ...) ALOGW("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
     34 #define SP_LOGE(x, ...) ALOGE("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
     35 
     36 namespace android {
     37 
     38 class GraphicBuffer;
     39 class IGraphicBufferConsumer;
     40 class IGraphicBufferProducer;
     41 
     42 // Camera3StreamSplitter is an autonomous class that manages one input BufferQueue
     43 // and multiple output BufferQueues. By using the buffer attach and detach logic
     44 // in BufferQueue, it is able to present the illusion of a single split
     45 // BufferQueue, where each buffer queued to the input is available to be
     46 // acquired by each of the outputs, and is able to be dequeued by the input
     47 // again only once all of the outputs have released it.
     48 class Camera3StreamSplitter : public BnConsumerListener {
     49 public:
     50 
     51     // Constructor
     52     Camera3StreamSplitter() = default;
     53 
     54     // Connect to the stream splitter by creating buffer queue and connecting it
     55     // with output surfaces.
     56     status_t connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
     57             uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
     58             uint32_t height, android::PixelFormat format, sp<Surface>* consumer);
     59 
     60     // addOutput adds an output BufferQueue to the splitter. The splitter
     61     // connects to outputQueue as a CPU producer, and any buffers queued
     62     // to the input will be queued to each output. If any  output is abandoned
     63     // by its consumer, the splitter will abandon its input queue (see onAbandoned).
     64     //
     65     // A return value other than NO_ERROR means that an error has occurred and
     66     // outputQueue has not been added to the splitter. BAD_VALUE is returned if
     67     // outputQueue is NULL. See IGraphicBufferProducer::connect for explanations
     68     // of other error codes.
     69     status_t addOutput(size_t surfaceId, const sp<Surface>& outputQueue);
     70 
     71     //removeOutput will remove a BufferQueue that was previously added to
     72     //the splitter outputs. Any pending buffers in the BufferQueue will get
     73     //reclaimed.
     74     status_t removeOutput(size_t surfaceId);
     75 
     76     // Notification that the graphic buffer has been released to the input
     77     // BufferQueue. The buffer should be reused by the camera device instead of
     78     // queuing to the outputs.
     79     status_t notifyBufferReleased(const sp<GraphicBuffer>& buffer);
     80 
     81     // Attach a buffer to the specified outputs. This call reserves a buffer
     82     // slot in the output queue.
     83     status_t attachBufferToOutputs(ANativeWindowBuffer* anb,
     84             const std::vector<size_t>& surface_ids);
     85 
     86     // Get return value of onFrameAvailable to work around problem that
     87     // onFrameAvailable is void. This function should be called by the producer
     88     // right after calling queueBuffer().
     89     status_t getOnFrameAvailableResult();
     90 
     91     // Disconnect the buffer queue from output surfaces.
     92     void disconnect();
     93 
     94 private:
     95     // From IConsumerListener
     96     //
     97     // During this callback, we store some tracking information, detach the
     98     // buffer from the input, and attach it to each of the outputs. This call
     99     // can block if there are too many outstanding buffers. If it blocks, it
    100     // will resume when onBufferReleasedByOutput releases a buffer back to the
    101     // input.
    102     void onFrameAvailable(const BufferItem& item) override;
    103 
    104     // From IConsumerListener
    105     // We don't care about released buffers because we detach each buffer as
    106     // soon as we acquire it. See the comment for onBufferReleased below for
    107     // some clarifying notes about the name.
    108     void onBuffersReleased() override {}
    109 
    110     // From IConsumerListener
    111     // We don't care about sideband streams, since we won't be splitting them
    112     void onSidebandStreamChanged() override {}
    113 
    114     // This is the implementation of the onBufferReleased callback from
    115     // IProducerListener. It gets called from an OutputListener (see below), and
    116     // 'from' is which producer interface from which the callback was received.
    117     //
    118     // During this callback, we detach the buffer from the output queue that
    119     // generated the callback, update our state tracking to see if this is the
    120     // last output releasing the buffer, and if so, release it to the input.
    121     // If we release the buffer to the input, we allow a blocked
    122     // onFrameAvailable call to proceed.
    123     void onBufferReleasedByOutput(const sp<IGraphicBufferProducer>& from);
    124 
    125     // Called by outputBufferLocked when a buffer in the async buffer queue got replaced.
    126     void onBufferReplacedLocked(const sp<IGraphicBufferProducer>& from, size_t surfaceId);
    127 
    128     // When this is called, the splitter disconnects from (i.e., abandons) its
    129     // input queue and signals any waiting onFrameAvailable calls to wake up.
    130     // It still processes callbacks from other outputs, but only detaches their
    131     // buffers so they can continue operating until they run out of buffers to
    132     // acquire. This must be called with mMutex locked.
    133     void onAbandonedLocked();
    134 
    135     // Decrement the buffer's reference count. Once the reference count becomes
    136     // 0, return the buffer back to the input BufferQueue.
    137     void decrementBufRefCountLocked(uint64_t id, size_t surfaceId);
    138 
    139     // Check for and handle any output surface dequeue errors.
    140     void handleOutputDequeueStatusLocked(status_t res, int slot);
    141 
    142     // Handles released output surface buffers.
    143     void returnOutputBufferLocked(const sp<Fence>& fence, const sp<IGraphicBufferProducer>& from,
    144             size_t surfaceId, int slot);
    145 
    146     // This is a thin wrapper class that lets us determine which BufferQueue
    147     // the IProducerListener::onBufferReleased callback is associated with. We
    148     // create one of these per output BufferQueue, and then pass the producer
    149     // into onBufferReleasedByOutput above.
    150     class OutputListener : public BnProducerListener,
    151                            public IBinder::DeathRecipient {
    152     public:
    153         OutputListener(wp<Camera3StreamSplitter> splitter,
    154                 wp<IGraphicBufferProducer> output);
    155         virtual ~OutputListener() = default;
    156 
    157         // From IProducerListener
    158         void onBufferReleased() override;
    159 
    160         // From IBinder::DeathRecipient
    161         void binderDied(const wp<IBinder>& who) override;
    162 
    163     private:
    164         wp<Camera3StreamSplitter> mSplitter;
    165         wp<IGraphicBufferProducer> mOutput;
    166     };
    167 
    168     class BufferTracker {
    169     public:
    170         BufferTracker(const sp<GraphicBuffer>& buffer,
    171                 const std::vector<size_t>& requestedSurfaces);
    172         ~BufferTracker() = default;
    173 
    174         const sp<GraphicBuffer>& getBuffer() const { return mBuffer; }
    175         const sp<Fence>& getMergedFence() const { return mMergedFence; }
    176 
    177         void mergeFence(const sp<Fence>& with);
    178 
    179         // Returns the new value
    180         // Only called while mMutex is held
    181         size_t decrementReferenceCountLocked(size_t surfaceId);
    182 
    183         const std::vector<size_t> requestedSurfaces() const { return mRequestedSurfaces; }
    184 
    185     private:
    186 
    187         // Disallow copying
    188         BufferTracker(const BufferTracker& other);
    189         BufferTracker& operator=(const BufferTracker& other);
    190 
    191         sp<GraphicBuffer> mBuffer; // One instance that holds this native handle
    192         sp<Fence> mMergedFence;
    193 
    194         // Request surfaces for a particular buffer. And when the buffer becomes
    195         // available from the input queue, the registered surfaces are used to decide
    196         // which output is the buffer sent to.
    197         std::vector<size_t> mRequestedSurfaces;
    198         size_t mReferenceCount;
    199     };
    200 
    201     // Must be accessed through RefBase
    202     virtual ~Camera3StreamSplitter();
    203 
    204     status_t addOutputLocked(size_t surfaceId, const sp<Surface>& outputQueue);
    205 
    206     status_t removeOutputLocked(size_t surfaceId);
    207 
    208     // Send a buffer to particular output, and increment the reference count
    209     // of the buffer. If this output is abandoned, the buffer's reference count
    210     // won't be incremented.
    211     status_t outputBufferLocked(const sp<IGraphicBufferProducer>& output,
    212             const BufferItem& bufferItem, size_t surfaceId);
    213 
    214     // Get unique name for the buffer queue consumer
    215     String8 getUniqueConsumerName();
    216 
    217     // Helper function to get the BufferQueue slot where a particular buffer is attached to.
    218     int getSlotForOutputLocked(const sp<IGraphicBufferProducer>& gbp,
    219             const sp<GraphicBuffer>& gb);
    220 
    221     // Sum of max consumer buffers for all outputs
    222     size_t mMaxConsumerBuffers = 0;
    223     size_t mMaxHalBuffers = 0;
    224     uint32_t mWidth = 0;
    225     uint32_t mHeight = 0;
    226     android::PixelFormat mFormat = android::PIXEL_FORMAT_NONE;
    227     uint64_t mProducerUsage = 0;
    228 
    229     static const nsecs_t kDequeueBufferTimeout   = s2ns(1); // 1 sec
    230 
    231     Mutex mMutex;
    232 
    233     sp<IGraphicBufferProducer> mProducer;
    234     sp<IGraphicBufferConsumer> mConsumer;
    235     sp<BufferItemConsumer> mBufferItemConsumer;
    236     sp<Surface> mSurface;
    237 
    238     //Map graphic buffer ids -> buffer items
    239     std::unordered_map<uint64_t, BufferItem> mInputSlots;
    240 
    241     //Map surface ids -> gbp outputs
    242     std::unordered_map<int, sp<IGraphicBufferProducer> > mOutputs;
    243 
    244     //Map surface ids -> consumer buffer count
    245     std::unordered_map<int, size_t > mConsumerBufferCount;
    246 
    247     // Map of GraphicBuffer IDs (GraphicBuffer::getId()) to buffer tracking
    248     // objects (which are mostly for counting how many outputs have released the
    249     // buffer, but also contain merged release fences).
    250     std::unordered_map<uint64_t, std::unique_ptr<BufferTracker> > mBuffers;
    251 
    252     struct GBPHash {
    253         std::size_t operator()(const sp<IGraphicBufferProducer>& producer) const {
    254             return std::hash<IGraphicBufferProducer *>{}(producer.get());
    255         }
    256     };
    257 
    258     std::unordered_map<sp<IGraphicBufferProducer>, sp<OutputListener>,
    259             GBPHash> mNotifiers;
    260 
    261     typedef std::vector<sp<GraphicBuffer>> OutputSlots;
    262     std::unordered_map<sp<IGraphicBufferProducer>, std::unique_ptr<OutputSlots>,
    263             GBPHash> mOutputSlots;
    264 
    265     //A set of buffers that could potentially stay in some of the outputs after removal
    266     //and therefore should be detached from the input queue.
    267     std::unordered_set<uint64_t> mDetachedBuffers;
    268 
    269     // Latest onFrameAvailable return value
    270     std::atomic<status_t> mOnFrameAvailableRes{0};
    271 
    272     String8 mConsumerName;
    273 };
    274 
    275 } // namespace android
    276 
    277 #endif
    278