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
178f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn#include <inttypes.h>
188f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn
1999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#define LOG_TAG "StreamSplitter"
2099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#define ATRACE_TAG ATRACE_TAG_GRAPHICS
2199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza//#define LOG_NDEBUG 0
2299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
23dd26416fe135f93ef2c8570738f8e1ca5e2ca3a3Dan Stoza#include <gui/BufferItem.h>
2499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <gui/IGraphicBufferConsumer.h>
2599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <gui/IGraphicBufferProducer.h>
2699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <gui/StreamSplitter.h>
2799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
2899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <ui/GraphicBuffer.h>
2999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
3099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <binder/ProcessState.h>
3199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
3299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza#include <utils/Trace.h>
3399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
3499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozanamespace android {
3599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
3699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozastatus_t StreamSplitter::createSplitter(
3799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        const sp<IGraphicBufferConsumer>& inputQueue,
3899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        sp<StreamSplitter>* outSplitter) {
3999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (inputQueue == NULL) {
4099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        ALOGE("createSplitter: inputQueue must not be NULL");
4199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        return BAD_VALUE;
4299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
4399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (outSplitter == NULL) {
4499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        ALOGE("createSplitter: outSplitter must not be NULL");
4599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        return BAD_VALUE;
4699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
4799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
4899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    sp<StreamSplitter> splitter(new StreamSplitter(inputQueue));
4999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    status_t status = splitter->mInput->consumerConnect(splitter, false);
5099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (status == NO_ERROR) {
5199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        splitter->mInput->setConsumerName(String8("StreamSplitter"));
5299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        *outSplitter = splitter;
5399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
5499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    return status;
5599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
5699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
5799b18b447dec188bcec37b415603b9dd400fc7e1Dan StozaStreamSplitter::StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue)
5899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza      : mIsAbandoned(false), mMutex(), mReleaseCondition(),
5999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        mOutstandingBuffers(0), mInput(inputQueue), mOutputs(), mBuffers() {}
6099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
6199b18b447dec188bcec37b415603b9dd400fc7e1Dan StozaStreamSplitter::~StreamSplitter() {
6299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mInput->consumerDisconnect();
6399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    Vector<sp<IGraphicBufferProducer> >::iterator output = mOutputs.begin();
6499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    for (; output != mOutputs.end(); ++output) {
6599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        (*output)->disconnect(NATIVE_WINDOW_API_CPU);
6699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
6799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
6899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (mBuffers.size() > 0) {
698f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn        ALOGE("%zu buffers still being tracked", mBuffers.size());
7099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
7199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
7299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
7399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozastatus_t StreamSplitter::addOutput(
7499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        const sp<IGraphicBufferProducer>& outputQueue) {
7599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (outputQueue == NULL) {
7699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        ALOGE("addOutput: outputQueue must not be NULL");
7799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        return BAD_VALUE;
7899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
7999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
8099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    Mutex::Autolock lock(mMutex);
8199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
8299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
8399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    sp<OutputListener> listener(new OutputListener(this, outputQueue));
842ea926bda2fa30f3ba8d0ed2d2395a8ada952e6eMarco Nelissen    IInterface::asBinder(outputQueue)->linkToDeath(listener);
8599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    status_t status = outputQueue->connect(listener, NATIVE_WINDOW_API_CPU,
8699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            /* producerControlledByApp */ false, &queueBufferOutput);
8799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (status != NO_ERROR) {
8899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        ALOGE("addOutput: failed to connect (%d)", status);
8999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        return status;
9099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
9199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
9299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mOutputs.push_back(outputQueue);
9399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
9499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    return NO_ERROR;
9599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
9699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
9799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozavoid StreamSplitter::setName(const String8 &name) {
9899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    Mutex::Autolock lock(mMutex);
9999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mInput->setConsumerName(name);
10099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
10199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
1028dc55396fc9bc425b5e2c82e76a38080f2a655ffDan Stozavoid StreamSplitter::onFrameAvailable(const BufferItem& /* item */) {
10399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    ATRACE_CALL();
10499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    Mutex::Autolock lock(mMutex);
10599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
10699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // The current policy is that if any one consumer is consuming buffers too
10799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // slowly, the splitter will stall the rest of the outputs by not acquiring
10899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // any more buffers from the input. This will cause back pressure on the
10999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // input queue, slowing down its producer.
11099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
11199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // If there are too many outstanding buffers, we block until a buffer is
11299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // released back to the input in onBufferReleased
11399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    while (mOutstandingBuffers >= MAX_OUTSTANDING_BUFFERS) {
11499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        mReleaseCondition.wait(mMutex);
11599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
11699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        // If the splitter is abandoned while we are waiting, the release
11799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        // condition variable will be broadcast, and we should just return
11899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        // without attempting to do anything more (since the input queue will
11999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        // also be abandoned).
12099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        if (mIsAbandoned) {
12199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            return;
12299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        }
12399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
12499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    ++mOutstandingBuffers;
12599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
12699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // Acquire and detach the buffer from the input
127dd26416fe135f93ef2c8570738f8e1ca5e2ca3a3Dan Stoza    BufferItem bufferItem;
12899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    status_t status = mInput->acquireBuffer(&bufferItem, /* presentWhen */ 0);
12999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
13099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            "acquiring buffer from input failed (%d)", status);
13199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
1328f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn    ALOGV("acquired buffer %#" PRIx64 " from input",
13399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            bufferItem.mGraphicBuffer->getId());
13499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
13547650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos    status = mInput->detachBuffer(bufferItem.mSlot);
13699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
13799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            "detaching buffer from input failed (%d)", status);
13899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
13999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // Initialize our reference count for this buffer
14099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mBuffers.add(bufferItem.mGraphicBuffer->getId(),
14199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            new BufferTracker(bufferItem.mGraphicBuffer));
14299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
14399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    IGraphicBufferProducer::QueueBufferInput queueInput(
14499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp,
1455b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvala            bufferItem.mDataSpace, bufferItem.mCrop,
1465b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvala            static_cast<int32_t>(bufferItem.mScalingMode),
147567dbbb6dd42be5013fcde0dadb3316d85f2fa0dPablo Ceballos            bufferItem.mTransform, bufferItem.mFence);
14899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
14999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // Attach and queue the buffer to each of the outputs
15099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    Vector<sp<IGraphicBufferProducer> >::iterator output = mOutputs.begin();
15199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    for (; output != mOutputs.end(); ++output) {
15299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        int slot;
15399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        status = (*output)->attachBuffer(&slot, bufferItem.mGraphicBuffer);
15499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        if (status == NO_INIT) {
15599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            // If we just discovered that this output has been abandoned, note
15699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            // that, increment the release count so that we still release this
15799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            // buffer eventually, and move on to the next output
15899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            onAbandonedLocked();
15999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            mBuffers.editValueFor(bufferItem.mGraphicBuffer->getId())->
16099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza                    incrementReleaseCountLocked();
16199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            continue;
16299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        } else {
16399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
16499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza                    "attaching buffer to output failed (%d)", status);
16599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        }
16699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
16799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        IGraphicBufferProducer::QueueBufferOutput queueOutput;
16899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        status = (*output)->queueBuffer(slot, queueInput, &queueOutput);
16999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        if (status == NO_INIT) {
17099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            // If we just discovered that this output has been abandoned, note
17199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            // that, increment the release count so that we still release this
17299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            // buffer eventually, and move on to the next output
17399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            onAbandonedLocked();
17499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            mBuffers.editValueFor(bufferItem.mGraphicBuffer->getId())->
17599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza                    incrementReleaseCountLocked();
17699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            continue;
17799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        } else {
17899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
17999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza                    "queueing buffer to output failed (%d)", status);
18099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        }
18199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
1828f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn        ALOGV("queued buffer %#" PRIx64 " to output %p",
18399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza                bufferItem.mGraphicBuffer->getId(), output->get());
18499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
18599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
18699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
18799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozavoid StreamSplitter::onBufferReleasedByOutput(
18899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        const sp<IGraphicBufferProducer>& from) {
18999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    ATRACE_CALL();
19099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    Mutex::Autolock lock(mMutex);
19199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
19299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    sp<GraphicBuffer> buffer;
19399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    sp<Fence> fence;
19499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    status_t status = from->detachNextBuffer(&buffer, &fence);
19599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (status == NO_INIT) {
19699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        // If we just discovered that this output has been abandoned, note that,
19799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        // but we can't do anything else, since buffer is invalid
19899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        onAbandonedLocked();
19999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        return;
20099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    } else {
20199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
20299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza                "detaching buffer from output failed (%d)", status);
20399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
20499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
2058f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn    ALOGV("detached buffer %#" PRIx64 " from output %p",
2068f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn          buffer->getId(), from.get());
20799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
20899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    const sp<BufferTracker>& tracker = mBuffers.editValueFor(buffer->getId());
20999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
21099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // Merge the release fence of the incoming buffer so that the fence we send
21199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // back to the input includes all of the outputs' fences
21299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    tracker->mergeFence(fence);
21399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
21499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // Check to see if this is the last outstanding reference to this buffer
21599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    size_t releaseCount = tracker->incrementReleaseCountLocked();
2168f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn    ALOGV("buffer %#" PRIx64 " reference count %zu (of %zu)", buffer->getId(),
21799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            releaseCount, mOutputs.size());
21899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (releaseCount < mOutputs.size()) {
21999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        return;
22099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
22199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
22299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // If we've been abandoned, we can't return the buffer to the input, so just
22399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // stop tracking it and move on
22499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (mIsAbandoned) {
22599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        mBuffers.removeItem(buffer->getId());
22699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        return;
22799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
22899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
22999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // Attach and release the buffer back to the input
23099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    int consumerSlot;
23199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    status = mInput->attachBuffer(&consumerSlot, tracker->getBuffer());
23299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
23399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            "attaching buffer to input failed (%d)", status);
23499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
23599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    status = mInput->releaseBuffer(consumerSlot, /* frameNumber */ 0,
23699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, tracker->getMergedFence());
23799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
23899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza            "releasing buffer to input failed (%d)", status);
23999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
2408f515ce1c57379cafac4357bc4fdb61dd346ec5fMark Salyzyn    ALOGV("released buffer %#" PRIx64 " to input", buffer->getId());
24199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
24299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // We no longer need to track the buffer once it has been returned to the
24399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // input
24499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mBuffers.removeItem(buffer->getId());
24599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
24699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    // Notify any waiting onFrameAvailable calls
24799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    --mOutstandingBuffers;
24899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mReleaseCondition.signal();
24999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
25099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
25199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozavoid StreamSplitter::onAbandonedLocked() {
25299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    ALOGE("one of my outputs has abandoned me");
25399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    if (!mIsAbandoned) {
25499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        mInput->consumerDisconnect();
25599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    }
25699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mIsAbandoned = true;
25799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mReleaseCondition.broadcast();
25899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
25999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
26099b18b447dec188bcec37b415603b9dd400fc7e1Dan StozaStreamSplitter::OutputListener::OutputListener(
26199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        const sp<StreamSplitter>& splitter,
26299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza        const sp<IGraphicBufferProducer>& output)
26399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza      : mSplitter(splitter), mOutput(output) {}
26499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
26599b18b447dec188bcec37b415603b9dd400fc7e1Dan StozaStreamSplitter::OutputListener::~OutputListener() {}
26699b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
26799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozavoid StreamSplitter::OutputListener::onBufferReleased() {
26899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mSplitter->onBufferReleasedByOutput(mOutput);
26999b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
27099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
27199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozavoid StreamSplitter::OutputListener::binderDied(const wp<IBinder>& /* who */) {
27299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    Mutex::Autolock lock(mSplitter->mMutex);
27399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mSplitter->onAbandonedLocked();
27499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
27599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
27699b18b447dec188bcec37b415603b9dd400fc7e1Dan StozaStreamSplitter::BufferTracker::BufferTracker(const sp<GraphicBuffer>& buffer)
27799b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza      : mBuffer(buffer), mMergedFence(Fence::NO_FENCE), mReleaseCount(0) {}
27899b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
27999b18b447dec188bcec37b415603b9dd400fc7e1Dan StozaStreamSplitter::BufferTracker::~BufferTracker() {}
28099b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
28199b18b447dec188bcec37b415603b9dd400fc7e1Dan Stozavoid StreamSplitter::BufferTracker::mergeFence(const sp<Fence>& with) {
28299b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza    mMergedFence = Fence::merge(String8("StreamSplitter"), mMergedFence, with);
28399b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza}
28499b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza
28599b18b447dec188bcec37b415603b9dd400fc7e1Dan Stoza} // namespace android
286