StreamSplitter.h revision 99b18b447dec188bcec37b415603b9dd400fc7e1
199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza/* 299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * Copyright 2014 The Android Open Source Project 399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * 499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * Licensed under the Apache License, Version 2.0 (the "License"); 599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * you may not use this file except in compliance with the License. 699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * You may obtain a copy of the License at 799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * 899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * http://www.apache.org/licenses/LICENSE-2.0 999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * 1099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * Unless required by applicable law or agreed to in writing, software 1199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * distributed under the License is distributed on an "AS IS" BASIS, 1299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * See the License for the specific language governing permissions and 1499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza * limitations under the License. 1599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza */ 1699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 1799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#ifndef ANDROID_GUI_STREAMSPLITTER_H 1899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#define ANDROID_GUI_STREAMSPLITTER_H 1999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 2099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <gui/IConsumerListener.h> 2199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <gui/IProducerListener.h> 2299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 2399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <utils/Condition.h> 2499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <utils/KeyedVector.h> 2599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <utils/Mutex.h> 2699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <utils/StrongPointer.h> 2799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 2899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozanamespace android { 2999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 3099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozaclass GraphicBuffer; 3199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozaclass IGraphicBufferConsumer; 3299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozaclass IGraphicBufferProducer; 3399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 3499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza// StreamSplitter is an autonomous class that manages one input BufferQueue 3599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza// and multiple output BufferQueues. By using the buffer attach and detach logic 3699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza// in BufferQueue, it is able to present the illusion of a single split 3799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza// BufferQueue, where each buffer queued to the input is available to be 3899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza// acquired by each of the outputs, and is able to be dequeued by the input 3999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza// again only once all of the outputs have released it. 4099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozaclass StreamSplitter : public BnConsumerListener { 4199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozapublic: 4299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // createSplitter creates a new splitter, outSplitter, using inputQueue as 4399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // the input BufferQueue. Output BufferQueues must be added using addOutput 4499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // before queueing any buffers to the input. 4599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // 4699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // A return value other than NO_ERROR means that an error has occurred and 4799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // outSplitter has not been modified. BAD_VALUE is returned if inputQueue or 4899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // outSplitter is NULL. See IGraphicBufferConsumer::consumerConnect for 4999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // explanations of other error codes. 5099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza static status_t createSplitter(const sp<IGraphicBufferConsumer>& inputQueue, 5199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza sp<StreamSplitter>* outSplitter); 5299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 5399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // addOutput adds an output BufferQueue to the splitter. The splitter 5499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // connects to outputQueue as a CPU producer, and any buffers queued 5599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // to the input will be queued to each output. It is assumed that all of the 5699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // outputs are added before any buffers are queued on the input. If any 5799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // output is abandoned by its consumer, the splitter will abandon its input 5899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // queue (see onAbandoned). 5999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // 6099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // A return value other than NO_ERROR means that an error has occurred and 6199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // outputQueue has not been added to the splitter. BAD_VALUE is returned if 6299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // outputQueue is NULL. See IGraphicBufferProducer::connect for explanations 6399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // of other error codes. 6499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza status_t addOutput(const sp<IGraphicBufferProducer>& outputQueue); 6599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 6699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // setName sets the consumer name of the input queue 6799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza void setName(const String8& name); 6899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 6999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozaprivate: 7099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // From IConsumerListener 7199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // 7299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // During this callback, we store some tracking information, detach the 7399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // buffer from the input, and attach it to each of the outputs. This call 7499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // can block if there are too many outstanding buffers. If it blocks, it 7599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // will resume when onBufferReleasedByOutput releases a buffer back to the 7699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // input. 7799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza virtual void onFrameAvailable(); 7899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 7999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // From IConsumerListener 8099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // We don't care about released buffers because we detach each buffer as 8199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // soon as we acquire it. See the comment for onBufferReleased below for 8299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // some clarifying notes about the name. 8399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza virtual void onBuffersReleased() {} 8499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 8599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // From IConsumerListener 8699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // We don't care about sideband streams, since we won't be splitting them 8799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza virtual void onSidebandStreamChanged() {} 8899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 8999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // This is the implementation of the onBufferReleased callback from 9099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // IProducerListener. It gets called from an OutputListener (see below), and 9199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // 'from' is which producer interface from which the callback was received. 9299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // 9399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // During this callback, we detach the buffer from the output queue that 9499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // generated the callback, update our state tracking to see if this is the 9599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // last output releasing the buffer, and if so, release it to the input. 9699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // If we release the buffer to the input, we allow a blocked 9799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // onFrameAvailable call to proceed. 9899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza void onBufferReleasedByOutput(const sp<IGraphicBufferProducer>& from); 9999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 10099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // When this is called, the splitter disconnects from (i.e., abandons) its 10199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // input queue and signals any waiting onFrameAvailable calls to wake up. 10299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // It still processes callbacks from other outputs, but only detaches their 10399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // buffers so they can continue operating until they run out of buffers to 10499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // acquire. This must be called with mMutex locked. 10599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza void onAbandonedLocked(); 10699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 10799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // This is a thin wrapper class that lets us determine which BufferQueue 10899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // the IProducerListener::onBufferReleased callback is associated with. We 10999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // create one of these per output BufferQueue, and then pass the producer 11099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // into onBufferReleasedByOutput above. 11199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza class OutputListener : public BnProducerListener, 11299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza public IBinder::DeathRecipient { 11399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza public: 11499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza OutputListener(const sp<StreamSplitter>& splitter, 11599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza const sp<IGraphicBufferProducer>& output); 11699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza virtual ~OutputListener(); 11799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 11899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // From IProducerListener 11999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza virtual void onBufferReleased(); 12099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 12199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // From IBinder::DeathRecipient 12299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza virtual void binderDied(const wp<IBinder>& who); 12399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 12499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza private: 12599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza sp<StreamSplitter> mSplitter; 12699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza sp<IGraphicBufferProducer> mOutput; 12799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza }; 12899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 12999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza class BufferTracker : public LightRefBase<BufferTracker> { 13099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza public: 13199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza BufferTracker(const sp<GraphicBuffer>& buffer); 13299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 13399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza const sp<GraphicBuffer>& getBuffer() const { return mBuffer; } 13499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza const sp<Fence>& getMergedFence() const { return mMergedFence; } 13599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 13699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza void mergeFence(const sp<Fence>& with); 13799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 13899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // Returns the new value 13999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // Only called while mMutex is held 14099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza size_t incrementReleaseCountLocked() { return ++mReleaseCount; } 14199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 14299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza private: 14399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // Only destroy through LightRefBase 14499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza friend LightRefBase<BufferTracker>; 14599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza ~BufferTracker(); 14699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 14799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // Disallow copying 14899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza BufferTracker(const BufferTracker& other); 14999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza BufferTracker& operator=(const BufferTracker& other); 15099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 15199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza sp<GraphicBuffer> mBuffer; // One instance that holds this native handle 15299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza sp<Fence> mMergedFence; 15399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza size_t mReleaseCount; 15499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza }; 15599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 15699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // Only called from createSplitter 15799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue); 15899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 15999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // Must be accessed through RefBase 16099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza virtual ~StreamSplitter(); 16199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 16299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza static const int MAX_OUTSTANDING_BUFFERS = 2; 16399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 16499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // mIsAbandoned is set to true when an output dies. Once the StreamSplitter 16599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // has been abandoned, it will continue to detach buffers from other 16699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // outputs, but it will disconnect from the input and not attempt to 16799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // communicate with it further. 16899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza bool mIsAbandoned; 16999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 17099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza Mutex mMutex; 17199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza Condition mReleaseCondition; 17299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza int mOutstandingBuffers; 17399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza sp<IGraphicBufferConsumer> mInput; 17499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza Vector<sp<IGraphicBufferProducer> > mOutputs; 17599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 17699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // Map of GraphicBuffer IDs (GraphicBuffer::getId()) to buffer tracking 17799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // objects (which are mostly for counting how many outputs have released the 17899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza // buffer, but also contain merged release fences). 17999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza KeyedVector<uint64_t, sp<BufferTracker> > mBuffers; 18099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}; 18199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 18299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza} // namespace android 18399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza 18499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#endif 185