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