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