1*38e8c45fSAndroid Build Coastguard Worker /* 2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project 3*38e8c45fSAndroid Build Coastguard Worker * 4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*38e8c45fSAndroid Build Coastguard Worker * 8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*38e8c45fSAndroid Build Coastguard Worker * 10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License. 15*38e8c45fSAndroid Build Coastguard Worker */ 16*38e8c45fSAndroid Build Coastguard Worker 17*38e8c45fSAndroid Build Coastguard Worker #ifndef ANDROID_GUI_STREAMSPLITTER_H 18*38e8c45fSAndroid Build Coastguard Worker #define ANDROID_GUI_STREAMSPLITTER_H 19*38e8c45fSAndroid Build Coastguard Worker 20*38e8c45fSAndroid Build Coastguard Worker #include <gui/IConsumerListener.h> 21*38e8c45fSAndroid Build Coastguard Worker #include <gui/IProducerListener.h> 22*38e8c45fSAndroid Build Coastguard Worker 23*38e8c45fSAndroid Build Coastguard Worker #include <utils/Condition.h> 24*38e8c45fSAndroid Build Coastguard Worker #include <utils/KeyedVector.h> 25*38e8c45fSAndroid Build Coastguard Worker #include <utils/Mutex.h> 26*38e8c45fSAndroid Build Coastguard Worker #include <utils/StrongPointer.h> 27*38e8c45fSAndroid Build Coastguard Worker 28*38e8c45fSAndroid Build Coastguard Worker namespace android { 29*38e8c45fSAndroid Build Coastguard Worker 30*38e8c45fSAndroid Build Coastguard Worker class GraphicBuffer; 31*38e8c45fSAndroid Build Coastguard Worker class IGraphicBufferConsumer; 32*38e8c45fSAndroid Build Coastguard Worker class IGraphicBufferProducer; 33*38e8c45fSAndroid Build Coastguard Worker 34*38e8c45fSAndroid Build Coastguard Worker // StreamSplitter is an autonomous class that manages one input BufferQueue 35*38e8c45fSAndroid Build Coastguard Worker // and multiple output BufferQueues. By using the buffer attach and detach logic 36*38e8c45fSAndroid Build Coastguard Worker // in BufferQueue, it is able to present the illusion of a single split 37*38e8c45fSAndroid Build Coastguard Worker // BufferQueue, where each buffer queued to the input is available to be 38*38e8c45fSAndroid Build Coastguard Worker // acquired by each of the outputs, and is able to be dequeued by the input 39*38e8c45fSAndroid Build Coastguard Worker // again only once all of the outputs have released it. 40*38e8c45fSAndroid Build Coastguard Worker class StreamSplitter : public BnConsumerListener { 41*38e8c45fSAndroid Build Coastguard Worker public: 42*38e8c45fSAndroid Build Coastguard Worker // createSplitter creates a new splitter, outSplitter, using inputQueue as 43*38e8c45fSAndroid Build Coastguard Worker // the input BufferQueue. Output BufferQueues must be added using addOutput 44*38e8c45fSAndroid Build Coastguard Worker // before queueing any buffers to the input. 45*38e8c45fSAndroid Build Coastguard Worker // 46*38e8c45fSAndroid Build Coastguard Worker // A return value other than NO_ERROR means that an error has occurred and 47*38e8c45fSAndroid Build Coastguard Worker // outSplitter has not been modified. BAD_VALUE is returned if inputQueue or 48*38e8c45fSAndroid Build Coastguard Worker // outSplitter is NULL. See IGraphicBufferConsumer::consumerConnect for 49*38e8c45fSAndroid Build Coastguard Worker // explanations of other error codes. 50*38e8c45fSAndroid Build Coastguard Worker static status_t createSplitter(const sp<IGraphicBufferConsumer>& inputQueue, 51*38e8c45fSAndroid Build Coastguard Worker sp<StreamSplitter>* outSplitter); 52*38e8c45fSAndroid Build Coastguard Worker 53*38e8c45fSAndroid Build Coastguard Worker // addOutput adds an output BufferQueue to the splitter. The splitter 54*38e8c45fSAndroid Build Coastguard Worker // connects to outputQueue as a CPU producer, and any buffers queued 55*38e8c45fSAndroid Build Coastguard Worker // to the input will be queued to each output. It is assumed that all of the 56*38e8c45fSAndroid Build Coastguard Worker // outputs are added before any buffers are queued on the input. If any 57*38e8c45fSAndroid Build Coastguard Worker // output is abandoned by its consumer, the splitter will abandon its input 58*38e8c45fSAndroid Build Coastguard Worker // queue (see onAbandoned). 59*38e8c45fSAndroid Build Coastguard Worker // 60*38e8c45fSAndroid Build Coastguard Worker // A return value other than NO_ERROR means that an error has occurred and 61*38e8c45fSAndroid Build Coastguard Worker // outputQueue has not been added to the splitter. BAD_VALUE is returned if 62*38e8c45fSAndroid Build Coastguard Worker // outputQueue is NULL. See IGraphicBufferProducer::connect for explanations 63*38e8c45fSAndroid Build Coastguard Worker // of other error codes. 64*38e8c45fSAndroid Build Coastguard Worker status_t addOutput(const sp<IGraphicBufferProducer>& outputQueue); 65*38e8c45fSAndroid Build Coastguard Worker 66*38e8c45fSAndroid Build Coastguard Worker // setName sets the consumer name of the input queue 67*38e8c45fSAndroid Build Coastguard Worker void setName(const String8& name); 68*38e8c45fSAndroid Build Coastguard Worker 69*38e8c45fSAndroid Build Coastguard Worker private: 70*38e8c45fSAndroid Build Coastguard Worker // From IConsumerListener 71*38e8c45fSAndroid Build Coastguard Worker // 72*38e8c45fSAndroid Build Coastguard Worker // During this callback, we store some tracking information, detach the 73*38e8c45fSAndroid Build Coastguard Worker // buffer from the input, and attach it to each of the outputs. This call 74*38e8c45fSAndroid Build Coastguard Worker // can block if there are too many outstanding buffers. If it blocks, it 75*38e8c45fSAndroid Build Coastguard Worker // will resume when onBufferReleasedByOutput releases a buffer back to the 76*38e8c45fSAndroid Build Coastguard Worker // input. 77*38e8c45fSAndroid Build Coastguard Worker virtual void onFrameAvailable(const BufferItem& item); 78*38e8c45fSAndroid Build Coastguard Worker 79*38e8c45fSAndroid Build Coastguard Worker // From IConsumerListener 80*38e8c45fSAndroid Build Coastguard Worker // We don't care about released buffers because we detach each buffer as 81*38e8c45fSAndroid Build Coastguard Worker // soon as we acquire it. See the comment for onBufferReleased below for 82*38e8c45fSAndroid Build Coastguard Worker // some clarifying notes about the name. onBuffersReleased()83*38e8c45fSAndroid Build Coastguard Worker virtual void onBuffersReleased() {} 84*38e8c45fSAndroid Build Coastguard Worker 85*38e8c45fSAndroid Build Coastguard Worker // From IConsumerListener 86*38e8c45fSAndroid Build Coastguard Worker // We don't care about sideband streams, since we won't be splitting them onSidebandStreamChanged()87*38e8c45fSAndroid Build Coastguard Worker virtual void onSidebandStreamChanged() {} 88*38e8c45fSAndroid Build Coastguard Worker 89*38e8c45fSAndroid Build Coastguard Worker // This is the implementation of the onBufferReleased callback from 90*38e8c45fSAndroid Build Coastguard Worker // IProducerListener. It gets called from an OutputListener (see below), and 91*38e8c45fSAndroid Build Coastguard Worker // 'from' is which producer interface from which the callback was received. 92*38e8c45fSAndroid Build Coastguard Worker // 93*38e8c45fSAndroid Build Coastguard Worker // During this callback, we detach the buffer from the output queue that 94*38e8c45fSAndroid Build Coastguard Worker // generated the callback, update our state tracking to see if this is the 95*38e8c45fSAndroid Build Coastguard Worker // last output releasing the buffer, and if so, release it to the input. 96*38e8c45fSAndroid Build Coastguard Worker // If we release the buffer to the input, we allow a blocked 97*38e8c45fSAndroid Build Coastguard Worker // onFrameAvailable call to proceed. 98*38e8c45fSAndroid Build Coastguard Worker void onBufferReleasedByOutput(const sp<IGraphicBufferProducer>& from); 99*38e8c45fSAndroid Build Coastguard Worker 100*38e8c45fSAndroid Build Coastguard Worker // When this is called, the splitter disconnects from (i.e., abandons) its 101*38e8c45fSAndroid Build Coastguard Worker // input queue and signals any waiting onFrameAvailable calls to wake up. 102*38e8c45fSAndroid Build Coastguard Worker // It still processes callbacks from other outputs, but only detaches their 103*38e8c45fSAndroid Build Coastguard Worker // buffers so they can continue operating until they run out of buffers to 104*38e8c45fSAndroid Build Coastguard Worker // acquire. This must be called with mMutex locked. 105*38e8c45fSAndroid Build Coastguard Worker void onAbandonedLocked(); 106*38e8c45fSAndroid Build Coastguard Worker 107*38e8c45fSAndroid Build Coastguard Worker // This is a thin wrapper class that lets us determine which BufferQueue 108*38e8c45fSAndroid Build Coastguard Worker // the IProducerListener::onBufferReleased callback is associated with. We 109*38e8c45fSAndroid Build Coastguard Worker // create one of these per output BufferQueue, and then pass the producer 110*38e8c45fSAndroid Build Coastguard Worker // into onBufferReleasedByOutput above. 111*38e8c45fSAndroid Build Coastguard Worker class OutputListener : public BnProducerListener, 112*38e8c45fSAndroid Build Coastguard Worker public IBinder::DeathRecipient { 113*38e8c45fSAndroid Build Coastguard Worker public: 114*38e8c45fSAndroid Build Coastguard Worker OutputListener(const sp<StreamSplitter>& splitter, 115*38e8c45fSAndroid Build Coastguard Worker const sp<IGraphicBufferProducer>& output); 116*38e8c45fSAndroid Build Coastguard Worker virtual ~OutputListener(); 117*38e8c45fSAndroid Build Coastguard Worker 118*38e8c45fSAndroid Build Coastguard Worker // From IProducerListener 119*38e8c45fSAndroid Build Coastguard Worker virtual void onBufferReleased(); 120*38e8c45fSAndroid Build Coastguard Worker 121*38e8c45fSAndroid Build Coastguard Worker // From IBinder::DeathRecipient 122*38e8c45fSAndroid Build Coastguard Worker virtual void binderDied(const wp<IBinder>& who); 123*38e8c45fSAndroid Build Coastguard Worker 124*38e8c45fSAndroid Build Coastguard Worker private: 125*38e8c45fSAndroid Build Coastguard Worker sp<StreamSplitter> mSplitter; 126*38e8c45fSAndroid Build Coastguard Worker sp<IGraphicBufferProducer> mOutput; 127*38e8c45fSAndroid Build Coastguard Worker }; 128*38e8c45fSAndroid Build Coastguard Worker 129*38e8c45fSAndroid Build Coastguard Worker class BufferTracker : public LightRefBase<BufferTracker> { 130*38e8c45fSAndroid Build Coastguard Worker public: 131*38e8c45fSAndroid Build Coastguard Worker explicit BufferTracker(const sp<GraphicBuffer>& buffer); 132*38e8c45fSAndroid Build Coastguard Worker getBuffer()133*38e8c45fSAndroid Build Coastguard Worker const sp<GraphicBuffer>& getBuffer() const { return mBuffer; } getMergedFence()134*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& getMergedFence() const { return mMergedFence; } 135*38e8c45fSAndroid Build Coastguard Worker 136*38e8c45fSAndroid Build Coastguard Worker void mergeFence(const sp<Fence>& with); 137*38e8c45fSAndroid Build Coastguard Worker 138*38e8c45fSAndroid Build Coastguard Worker // Returns the new value 139*38e8c45fSAndroid Build Coastguard Worker // Only called while mMutex is held incrementReleaseCountLocked()140*38e8c45fSAndroid Build Coastguard Worker size_t incrementReleaseCountLocked() { return ++mReleaseCount; } 141*38e8c45fSAndroid Build Coastguard Worker 142*38e8c45fSAndroid Build Coastguard Worker private: 143*38e8c45fSAndroid Build Coastguard Worker // Only destroy through LightRefBase 144*38e8c45fSAndroid Build Coastguard Worker friend LightRefBase<BufferTracker>; 145*38e8c45fSAndroid Build Coastguard Worker ~BufferTracker(); 146*38e8c45fSAndroid Build Coastguard Worker 147*38e8c45fSAndroid Build Coastguard Worker // Disallow copying 148*38e8c45fSAndroid Build Coastguard Worker BufferTracker(const BufferTracker& other); 149*38e8c45fSAndroid Build Coastguard Worker BufferTracker& operator=(const BufferTracker& other); 150*38e8c45fSAndroid Build Coastguard Worker 151*38e8c45fSAndroid Build Coastguard Worker sp<GraphicBuffer> mBuffer; // One instance that holds this native handle 152*38e8c45fSAndroid Build Coastguard Worker sp<Fence> mMergedFence; 153*38e8c45fSAndroid Build Coastguard Worker size_t mReleaseCount; 154*38e8c45fSAndroid Build Coastguard Worker }; 155*38e8c45fSAndroid Build Coastguard Worker 156*38e8c45fSAndroid Build Coastguard Worker // Only called from createSplitter 157*38e8c45fSAndroid Build Coastguard Worker explicit StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue); 158*38e8c45fSAndroid Build Coastguard Worker 159*38e8c45fSAndroid Build Coastguard Worker // Must be accessed through RefBase 160*38e8c45fSAndroid Build Coastguard Worker virtual ~StreamSplitter(); 161*38e8c45fSAndroid Build Coastguard Worker 162*38e8c45fSAndroid Build Coastguard Worker static const int MAX_OUTSTANDING_BUFFERS = 2; 163*38e8c45fSAndroid Build Coastguard Worker 164*38e8c45fSAndroid Build Coastguard Worker // mIsAbandoned is set to true when an output dies. Once the StreamSplitter 165*38e8c45fSAndroid Build Coastguard Worker // has been abandoned, it will continue to detach buffers from other 166*38e8c45fSAndroid Build Coastguard Worker // outputs, but it will disconnect from the input and not attempt to 167*38e8c45fSAndroid Build Coastguard Worker // communicate with it further. 168*38e8c45fSAndroid Build Coastguard Worker bool mIsAbandoned; 169*38e8c45fSAndroid Build Coastguard Worker 170*38e8c45fSAndroid Build Coastguard Worker Mutex mMutex; 171*38e8c45fSAndroid Build Coastguard Worker Condition mReleaseCondition; 172*38e8c45fSAndroid Build Coastguard Worker int mOutstandingBuffers; 173*38e8c45fSAndroid Build Coastguard Worker sp<IGraphicBufferConsumer> mInput; 174*38e8c45fSAndroid Build Coastguard Worker Vector<sp<IGraphicBufferProducer> > mOutputs; 175*38e8c45fSAndroid Build Coastguard Worker 176*38e8c45fSAndroid Build Coastguard Worker // Map of GraphicBuffer IDs (GraphicBuffer::getId()) to buffer tracking 177*38e8c45fSAndroid Build Coastguard Worker // objects (which are mostly for counting how many outputs have released the 178*38e8c45fSAndroid Build Coastguard Worker // buffer, but also contain merged release fences). 179*38e8c45fSAndroid Build Coastguard Worker KeyedVector<uint64_t, sp<BufferTracker> > mBuffers; 180*38e8c45fSAndroid Build Coastguard Worker }; 181*38e8c45fSAndroid Build Coastguard Worker 182*38e8c45fSAndroid Build Coastguard Worker } // namespace android 183*38e8c45fSAndroid Build Coastguard Worker 184*38e8c45fSAndroid Build Coastguard Worker #endif 185