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
36namespace android {
37
38class GraphicBuffer;
39class IGraphicBufferConsumer;
40class 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.
48class Camera3StreamSplitter : public BnConsumerListener {
49public:
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
94private:
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