xref: /aosp_15_r20/frameworks/native/libs/gui/StreamSplitter.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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 #include <inttypes.h>
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "StreamSplitter"
20*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21*38e8c45fSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
22*38e8c45fSAndroid Build Coastguard Worker 
23*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferItem.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <gui/IGraphicBufferConsumer.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <gui/IGraphicBufferProducer.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <gui/StreamSplitter.h>
27*38e8c45fSAndroid Build Coastguard Worker 
28*38e8c45fSAndroid Build Coastguard Worker #include <ui/GraphicBuffer.h>
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker #include <binder/ProcessState.h>
31*38e8c45fSAndroid Build Coastguard Worker 
32*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker #include <system/window.h>
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker namespace android {
37*38e8c45fSAndroid Build Coastguard Worker 
createSplitter(const sp<IGraphicBufferConsumer> & inputQueue,sp<StreamSplitter> * outSplitter)38*38e8c45fSAndroid Build Coastguard Worker status_t StreamSplitter::createSplitter(
39*38e8c45fSAndroid Build Coastguard Worker         const sp<IGraphicBufferConsumer>& inputQueue,
40*38e8c45fSAndroid Build Coastguard Worker         sp<StreamSplitter>* outSplitter) {
41*38e8c45fSAndroid Build Coastguard Worker     if (inputQueue == nullptr) {
42*38e8c45fSAndroid Build Coastguard Worker         ALOGE("createSplitter: inputQueue must not be NULL");
43*38e8c45fSAndroid Build Coastguard Worker         return BAD_VALUE;
44*38e8c45fSAndroid Build Coastguard Worker     }
45*38e8c45fSAndroid Build Coastguard Worker     if (outSplitter == nullptr) {
46*38e8c45fSAndroid Build Coastguard Worker         ALOGE("createSplitter: outSplitter must not be NULL");
47*38e8c45fSAndroid Build Coastguard Worker         return BAD_VALUE;
48*38e8c45fSAndroid Build Coastguard Worker     }
49*38e8c45fSAndroid Build Coastguard Worker 
50*38e8c45fSAndroid Build Coastguard Worker     sp<StreamSplitter> splitter(new StreamSplitter(inputQueue));
51*38e8c45fSAndroid Build Coastguard Worker     status_t status = splitter->mInput->consumerConnect(splitter, false);
52*38e8c45fSAndroid Build Coastguard Worker     if (status == NO_ERROR) {
53*38e8c45fSAndroid Build Coastguard Worker         splitter->mInput->setConsumerName(String8("StreamSplitter"));
54*38e8c45fSAndroid Build Coastguard Worker         *outSplitter = splitter;
55*38e8c45fSAndroid Build Coastguard Worker     }
56*38e8c45fSAndroid Build Coastguard Worker     return status;
57*38e8c45fSAndroid Build Coastguard Worker }
58*38e8c45fSAndroid Build Coastguard Worker 
StreamSplitter(const sp<IGraphicBufferConsumer> & inputQueue)59*38e8c45fSAndroid Build Coastguard Worker StreamSplitter::StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue)
60*38e8c45fSAndroid Build Coastguard Worker       : mIsAbandoned(false), mMutex(), mReleaseCondition(),
61*38e8c45fSAndroid Build Coastguard Worker         mOutstandingBuffers(0), mInput(inputQueue), mOutputs(), mBuffers() {}
62*38e8c45fSAndroid Build Coastguard Worker 
~StreamSplitter()63*38e8c45fSAndroid Build Coastguard Worker StreamSplitter::~StreamSplitter() {
64*38e8c45fSAndroid Build Coastguard Worker     mInput->consumerDisconnect();
65*38e8c45fSAndroid Build Coastguard Worker     Vector<sp<IGraphicBufferProducer> >::iterator output = mOutputs.begin();
66*38e8c45fSAndroid Build Coastguard Worker     for (; output != mOutputs.end(); ++output) {
67*38e8c45fSAndroid Build Coastguard Worker         (*output)->disconnect(NATIVE_WINDOW_API_CPU);
68*38e8c45fSAndroid Build Coastguard Worker     }
69*38e8c45fSAndroid Build Coastguard Worker 
70*38e8c45fSAndroid Build Coastguard Worker     if (mBuffers.size() > 0) {
71*38e8c45fSAndroid Build Coastguard Worker         ALOGE("%zu buffers still being tracked", mBuffers.size());
72*38e8c45fSAndroid Build Coastguard Worker     }
73*38e8c45fSAndroid Build Coastguard Worker }
74*38e8c45fSAndroid Build Coastguard Worker 
addOutput(const sp<IGraphicBufferProducer> & outputQueue)75*38e8c45fSAndroid Build Coastguard Worker status_t StreamSplitter::addOutput(
76*38e8c45fSAndroid Build Coastguard Worker         const sp<IGraphicBufferProducer>& outputQueue) {
77*38e8c45fSAndroid Build Coastguard Worker     if (outputQueue == nullptr) {
78*38e8c45fSAndroid Build Coastguard Worker         ALOGE("addOutput: outputQueue must not be NULL");
79*38e8c45fSAndroid Build Coastguard Worker         return BAD_VALUE;
80*38e8c45fSAndroid Build Coastguard Worker     }
81*38e8c45fSAndroid Build Coastguard Worker 
82*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
83*38e8c45fSAndroid Build Coastguard Worker 
84*38e8c45fSAndroid Build Coastguard Worker     IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
85*38e8c45fSAndroid Build Coastguard Worker     sp<OutputListener> listener(new OutputListener(this, outputQueue));
86*38e8c45fSAndroid Build Coastguard Worker     IInterface::asBinder(outputQueue)->linkToDeath(listener);
87*38e8c45fSAndroid Build Coastguard Worker     status_t status = outputQueue->connect(listener, NATIVE_WINDOW_API_CPU,
88*38e8c45fSAndroid Build Coastguard Worker             /* producerControlledByApp */ false, &queueBufferOutput);
89*38e8c45fSAndroid Build Coastguard Worker     if (status != NO_ERROR) {
90*38e8c45fSAndroid Build Coastguard Worker         ALOGE("addOutput: failed to connect (%d)", status);
91*38e8c45fSAndroid Build Coastguard Worker         return status;
92*38e8c45fSAndroid Build Coastguard Worker     }
93*38e8c45fSAndroid Build Coastguard Worker 
94*38e8c45fSAndroid Build Coastguard Worker     mOutputs.push_back(outputQueue);
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
97*38e8c45fSAndroid Build Coastguard Worker }
98*38e8c45fSAndroid Build Coastguard Worker 
setName(const String8 & name)99*38e8c45fSAndroid Build Coastguard Worker void StreamSplitter::setName(const String8 &name) {
100*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
101*38e8c45fSAndroid Build Coastguard Worker     mInput->setConsumerName(name);
102*38e8c45fSAndroid Build Coastguard Worker }
103*38e8c45fSAndroid Build Coastguard Worker 
onFrameAvailable(const BufferItem &)104*38e8c45fSAndroid Build Coastguard Worker void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) {
105*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
106*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
107*38e8c45fSAndroid Build Coastguard Worker 
108*38e8c45fSAndroid Build Coastguard Worker     // The current policy is that if any one consumer is consuming buffers too
109*38e8c45fSAndroid Build Coastguard Worker     // slowly, the splitter will stall the rest of the outputs by not acquiring
110*38e8c45fSAndroid Build Coastguard Worker     // any more buffers from the input. This will cause back pressure on the
111*38e8c45fSAndroid Build Coastguard Worker     // input queue, slowing down its producer.
112*38e8c45fSAndroid Build Coastguard Worker 
113*38e8c45fSAndroid Build Coastguard Worker     // If there are too many outstanding buffers, we block until a buffer is
114*38e8c45fSAndroid Build Coastguard Worker     // released back to the input in onBufferReleased
115*38e8c45fSAndroid Build Coastguard Worker     while (mOutstandingBuffers >= MAX_OUTSTANDING_BUFFERS) {
116*38e8c45fSAndroid Build Coastguard Worker         mReleaseCondition.wait(mMutex);
117*38e8c45fSAndroid Build Coastguard Worker 
118*38e8c45fSAndroid Build Coastguard Worker         // If the splitter is abandoned while we are waiting, the release
119*38e8c45fSAndroid Build Coastguard Worker         // condition variable will be broadcast, and we should just return
120*38e8c45fSAndroid Build Coastguard Worker         // without attempting to do anything more (since the input queue will
121*38e8c45fSAndroid Build Coastguard Worker         // also be abandoned).
122*38e8c45fSAndroid Build Coastguard Worker         if (mIsAbandoned) {
123*38e8c45fSAndroid Build Coastguard Worker             return;
124*38e8c45fSAndroid Build Coastguard Worker         }
125*38e8c45fSAndroid Build Coastguard Worker     }
126*38e8c45fSAndroid Build Coastguard Worker     ++mOutstandingBuffers;
127*38e8c45fSAndroid Build Coastguard Worker 
128*38e8c45fSAndroid Build Coastguard Worker     // Acquire and detach the buffer from the input
129*38e8c45fSAndroid Build Coastguard Worker     BufferItem bufferItem;
130*38e8c45fSAndroid Build Coastguard Worker     status_t status = mInput->acquireBuffer(&bufferItem, /* presentWhen */ 0);
131*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
132*38e8c45fSAndroid Build Coastguard Worker             "acquiring buffer from input failed (%d)", status);
133*38e8c45fSAndroid Build Coastguard Worker 
134*38e8c45fSAndroid Build Coastguard Worker     ALOGV("acquired buffer %#" PRIx64 " from input",
135*38e8c45fSAndroid Build Coastguard Worker             bufferItem.mGraphicBuffer->getId());
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker     status = mInput->detachBuffer(bufferItem.mSlot);
138*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
139*38e8c45fSAndroid Build Coastguard Worker             "detaching buffer from input failed (%d)", status);
140*38e8c45fSAndroid Build Coastguard Worker 
141*38e8c45fSAndroid Build Coastguard Worker     // Initialize our reference count for this buffer
142*38e8c45fSAndroid Build Coastguard Worker     mBuffers.add(bufferItem.mGraphicBuffer->getId(),
143*38e8c45fSAndroid Build Coastguard Worker             new BufferTracker(bufferItem.mGraphicBuffer));
144*38e8c45fSAndroid Build Coastguard Worker 
145*38e8c45fSAndroid Build Coastguard Worker     IGraphicBufferProducer::QueueBufferInput queueInput(
146*38e8c45fSAndroid Build Coastguard Worker             bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp,
147*38e8c45fSAndroid Build Coastguard Worker             bufferItem.mDataSpace, bufferItem.mCrop,
148*38e8c45fSAndroid Build Coastguard Worker             static_cast<int32_t>(bufferItem.mScalingMode),
149*38e8c45fSAndroid Build Coastguard Worker             bufferItem.mTransform, bufferItem.mFence);
150*38e8c45fSAndroid Build Coastguard Worker 
151*38e8c45fSAndroid Build Coastguard Worker     // Attach and queue the buffer to each of the outputs
152*38e8c45fSAndroid Build Coastguard Worker     Vector<sp<IGraphicBufferProducer> >::iterator output = mOutputs.begin();
153*38e8c45fSAndroid Build Coastguard Worker     for (; output != mOutputs.end(); ++output) {
154*38e8c45fSAndroid Build Coastguard Worker         int slot;
155*38e8c45fSAndroid Build Coastguard Worker         status = (*output)->attachBuffer(&slot, bufferItem.mGraphicBuffer);
156*38e8c45fSAndroid Build Coastguard Worker         if (status == NO_INIT) {
157*38e8c45fSAndroid Build Coastguard Worker             // If we just discovered that this output has been abandoned, note
158*38e8c45fSAndroid Build Coastguard Worker             // that, increment the release count so that we still release this
159*38e8c45fSAndroid Build Coastguard Worker             // buffer eventually, and move on to the next output
160*38e8c45fSAndroid Build Coastguard Worker             onAbandonedLocked();
161*38e8c45fSAndroid Build Coastguard Worker             mBuffers.editValueFor(bufferItem.mGraphicBuffer->getId())->
162*38e8c45fSAndroid Build Coastguard Worker                     incrementReleaseCountLocked();
163*38e8c45fSAndroid Build Coastguard Worker             continue;
164*38e8c45fSAndroid Build Coastguard Worker         } else {
165*38e8c45fSAndroid Build Coastguard Worker             LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
166*38e8c45fSAndroid Build Coastguard Worker                     "attaching buffer to output failed (%d)", status);
167*38e8c45fSAndroid Build Coastguard Worker         }
168*38e8c45fSAndroid Build Coastguard Worker 
169*38e8c45fSAndroid Build Coastguard Worker         IGraphicBufferProducer::QueueBufferOutput queueOutput;
170*38e8c45fSAndroid Build Coastguard Worker         status = (*output)->queueBuffer(slot, queueInput, &queueOutput);
171*38e8c45fSAndroid Build Coastguard Worker         if (status == NO_INIT) {
172*38e8c45fSAndroid Build Coastguard Worker             // If we just discovered that this output has been abandoned, note
173*38e8c45fSAndroid Build Coastguard Worker             // that, increment the release count so that we still release this
174*38e8c45fSAndroid Build Coastguard Worker             // buffer eventually, and move on to the next output
175*38e8c45fSAndroid Build Coastguard Worker             onAbandonedLocked();
176*38e8c45fSAndroid Build Coastguard Worker             mBuffers.editValueFor(bufferItem.mGraphicBuffer->getId())->
177*38e8c45fSAndroid Build Coastguard Worker                     incrementReleaseCountLocked();
178*38e8c45fSAndroid Build Coastguard Worker             continue;
179*38e8c45fSAndroid Build Coastguard Worker         } else {
180*38e8c45fSAndroid Build Coastguard Worker             LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
181*38e8c45fSAndroid Build Coastguard Worker                     "queueing buffer to output failed (%d)", status);
182*38e8c45fSAndroid Build Coastguard Worker         }
183*38e8c45fSAndroid Build Coastguard Worker 
184*38e8c45fSAndroid Build Coastguard Worker         ALOGV("queued buffer %#" PRIx64 " to output %p",
185*38e8c45fSAndroid Build Coastguard Worker                 bufferItem.mGraphicBuffer->getId(), output->get());
186*38e8c45fSAndroid Build Coastguard Worker     }
187*38e8c45fSAndroid Build Coastguard Worker }
188*38e8c45fSAndroid Build Coastguard Worker 
onBufferReleasedByOutput(const sp<IGraphicBufferProducer> & from)189*38e8c45fSAndroid Build Coastguard Worker void StreamSplitter::onBufferReleasedByOutput(
190*38e8c45fSAndroid Build Coastguard Worker         const sp<IGraphicBufferProducer>& from) {
191*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
192*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
193*38e8c45fSAndroid Build Coastguard Worker 
194*38e8c45fSAndroid Build Coastguard Worker     sp<GraphicBuffer> buffer;
195*38e8c45fSAndroid Build Coastguard Worker     sp<Fence> fence;
196*38e8c45fSAndroid Build Coastguard Worker     status_t status = from->detachNextBuffer(&buffer, &fence);
197*38e8c45fSAndroid Build Coastguard Worker     if (status == NO_INIT) {
198*38e8c45fSAndroid Build Coastguard Worker         // If we just discovered that this output has been abandoned, note that,
199*38e8c45fSAndroid Build Coastguard Worker         // but we can't do anything else, since buffer is invalid
200*38e8c45fSAndroid Build Coastguard Worker         onAbandonedLocked();
201*38e8c45fSAndroid Build Coastguard Worker         return;
202*38e8c45fSAndroid Build Coastguard Worker     } else {
203*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
204*38e8c45fSAndroid Build Coastguard Worker                 "detaching buffer from output failed (%d)", status);
205*38e8c45fSAndroid Build Coastguard Worker     }
206*38e8c45fSAndroid Build Coastguard Worker 
207*38e8c45fSAndroid Build Coastguard Worker     ALOGV("detached buffer %#" PRIx64 " from output %p",
208*38e8c45fSAndroid Build Coastguard Worker           buffer->getId(), from.get());
209*38e8c45fSAndroid Build Coastguard Worker 
210*38e8c45fSAndroid Build Coastguard Worker     const sp<BufferTracker>& tracker = mBuffers.editValueFor(buffer->getId());
211*38e8c45fSAndroid Build Coastguard Worker 
212*38e8c45fSAndroid Build Coastguard Worker     // Merge the release fence of the incoming buffer so that the fence we send
213*38e8c45fSAndroid Build Coastguard Worker     // back to the input includes all of the outputs' fences
214*38e8c45fSAndroid Build Coastguard Worker     tracker->mergeFence(fence);
215*38e8c45fSAndroid Build Coastguard Worker 
216*38e8c45fSAndroid Build Coastguard Worker     // Check to see if this is the last outstanding reference to this buffer
217*38e8c45fSAndroid Build Coastguard Worker     size_t releaseCount = tracker->incrementReleaseCountLocked();
218*38e8c45fSAndroid Build Coastguard Worker     ALOGV("buffer %#" PRIx64 " reference count %zu (of %zu)", buffer->getId(),
219*38e8c45fSAndroid Build Coastguard Worker             releaseCount, mOutputs.size());
220*38e8c45fSAndroid Build Coastguard Worker     if (releaseCount < mOutputs.size()) {
221*38e8c45fSAndroid Build Coastguard Worker         return;
222*38e8c45fSAndroid Build Coastguard Worker     }
223*38e8c45fSAndroid Build Coastguard Worker 
224*38e8c45fSAndroid Build Coastguard Worker     // If we've been abandoned, we can't return the buffer to the input, so just
225*38e8c45fSAndroid Build Coastguard Worker     // stop tracking it and move on
226*38e8c45fSAndroid Build Coastguard Worker     if (mIsAbandoned) {
227*38e8c45fSAndroid Build Coastguard Worker         mBuffers.removeItem(buffer->getId());
228*38e8c45fSAndroid Build Coastguard Worker         return;
229*38e8c45fSAndroid Build Coastguard Worker     }
230*38e8c45fSAndroid Build Coastguard Worker 
231*38e8c45fSAndroid Build Coastguard Worker     // Attach and release the buffer back to the input
232*38e8c45fSAndroid Build Coastguard Worker     int consumerSlot;
233*38e8c45fSAndroid Build Coastguard Worker     status = mInput->attachBuffer(&consumerSlot, tracker->getBuffer());
234*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
235*38e8c45fSAndroid Build Coastguard Worker             "attaching buffer to input failed (%d)", status);
236*38e8c45fSAndroid Build Coastguard Worker 
237*38e8c45fSAndroid Build Coastguard Worker     status = mInput->releaseBuffer(consumerSlot, /* frameNumber */ 0, tracker->getMergedFence());
238*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
239*38e8c45fSAndroid Build Coastguard Worker             "releasing buffer to input failed (%d)", status);
240*38e8c45fSAndroid Build Coastguard Worker 
241*38e8c45fSAndroid Build Coastguard Worker     ALOGV("released buffer %#" PRIx64 " to input", buffer->getId());
242*38e8c45fSAndroid Build Coastguard Worker 
243*38e8c45fSAndroid Build Coastguard Worker     // We no longer need to track the buffer once it has been returned to the
244*38e8c45fSAndroid Build Coastguard Worker     // input
245*38e8c45fSAndroid Build Coastguard Worker     mBuffers.removeItem(buffer->getId());
246*38e8c45fSAndroid Build Coastguard Worker 
247*38e8c45fSAndroid Build Coastguard Worker     // Notify any waiting onFrameAvailable calls
248*38e8c45fSAndroid Build Coastguard Worker     --mOutstandingBuffers;
249*38e8c45fSAndroid Build Coastguard Worker     mReleaseCondition.signal();
250*38e8c45fSAndroid Build Coastguard Worker }
251*38e8c45fSAndroid Build Coastguard Worker 
onAbandonedLocked()252*38e8c45fSAndroid Build Coastguard Worker void StreamSplitter::onAbandonedLocked() {
253*38e8c45fSAndroid Build Coastguard Worker     ALOGE("one of my outputs has abandoned me");
254*38e8c45fSAndroid Build Coastguard Worker     if (!mIsAbandoned) {
255*38e8c45fSAndroid Build Coastguard Worker         mInput->consumerDisconnect();
256*38e8c45fSAndroid Build Coastguard Worker     }
257*38e8c45fSAndroid Build Coastguard Worker     mIsAbandoned = true;
258*38e8c45fSAndroid Build Coastguard Worker     mReleaseCondition.broadcast();
259*38e8c45fSAndroid Build Coastguard Worker }
260*38e8c45fSAndroid Build Coastguard Worker 
OutputListener(const sp<StreamSplitter> & splitter,const sp<IGraphicBufferProducer> & output)261*38e8c45fSAndroid Build Coastguard Worker StreamSplitter::OutputListener::OutputListener(
262*38e8c45fSAndroid Build Coastguard Worker         const sp<StreamSplitter>& splitter,
263*38e8c45fSAndroid Build Coastguard Worker         const sp<IGraphicBufferProducer>& output)
264*38e8c45fSAndroid Build Coastguard Worker       : mSplitter(splitter), mOutput(output) {}
265*38e8c45fSAndroid Build Coastguard Worker 
~OutputListener()266*38e8c45fSAndroid Build Coastguard Worker StreamSplitter::OutputListener::~OutputListener() {}
267*38e8c45fSAndroid Build Coastguard Worker 
onBufferReleased()268*38e8c45fSAndroid Build Coastguard Worker void StreamSplitter::OutputListener::onBufferReleased() {
269*38e8c45fSAndroid Build Coastguard Worker     mSplitter->onBufferReleasedByOutput(mOutput);
270*38e8c45fSAndroid Build Coastguard Worker }
271*38e8c45fSAndroid Build Coastguard Worker 
binderDied(const wp<IBinder> &)272*38e8c45fSAndroid Build Coastguard Worker void StreamSplitter::OutputListener::binderDied(const wp<IBinder>& /* who */) {
273*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mSplitter->mMutex);
274*38e8c45fSAndroid Build Coastguard Worker     mSplitter->onAbandonedLocked();
275*38e8c45fSAndroid Build Coastguard Worker }
276*38e8c45fSAndroid Build Coastguard Worker 
BufferTracker(const sp<GraphicBuffer> & buffer)277*38e8c45fSAndroid Build Coastguard Worker StreamSplitter::BufferTracker::BufferTracker(const sp<GraphicBuffer>& buffer)
278*38e8c45fSAndroid Build Coastguard Worker       : mBuffer(buffer), mMergedFence(Fence::NO_FENCE), mReleaseCount(0) {}
279*38e8c45fSAndroid Build Coastguard Worker 
~BufferTracker()280*38e8c45fSAndroid Build Coastguard Worker StreamSplitter::BufferTracker::~BufferTracker() {}
281*38e8c45fSAndroid Build Coastguard Worker 
mergeFence(const sp<Fence> & with)282*38e8c45fSAndroid Build Coastguard Worker void StreamSplitter::BufferTracker::mergeFence(const sp<Fence>& with) {
283*38e8c45fSAndroid Build Coastguard Worker     mMergedFence = Fence::merge(String8("StreamSplitter"), mMergedFence, with);
284*38e8c45fSAndroid Build Coastguard Worker }
285*38e8c45fSAndroid Build Coastguard Worker 
286*38e8c45fSAndroid Build Coastguard Worker } // namespace android
287