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