diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2019-05-16 04:54:45 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2019-05-16 04:54:45 +0000 |
commit | 3d4739e5bfb3ad9008d9c8e8131b7c28fd06bdf0 (patch) | |
tree | c97b7be5a8d2eb026d55ef1e8b60774cce099384 | |
parent | 2d47a48e620b53772a062bb3f966461440da597b (diff) | |
parent | 520e1d07a7870f4256434d33e3ef9a21e6796d41 (diff) | |
download | av-3d4739e5bfb3ad9008d9c8e8131b7c28fd06bdf0.tar.gz |
Merge "RESTRICT AUTOMERGE Gate input buffers from input surface" into pi-dev
-rw-r--r-- | media/sfplugin/C2OMXNode.cpp | 12 | ||||
-rw-r--r-- | media/sfplugin/C2OMXNode.h | 10 | ||||
-rw-r--r-- | media/sfplugin/CCodec.cpp | 9 | ||||
-rw-r--r-- | media/sfplugin/CCodecBufferChannel.cpp | 46 | ||||
-rw-r--r-- | media/sfplugin/CCodecBufferChannel.h | 15 | ||||
-rw-r--r-- | media/sfplugin/InputSurfaceWrapper.h | 20 |
6 files changed, 104 insertions, 8 deletions
diff --git a/media/sfplugin/C2OMXNode.cpp b/media/sfplugin/C2OMXNode.cpp index 73cbbc6..92b86b6 100644 --- a/media/sfplugin/C2OMXNode.cpp +++ b/media/sfplugin/C2OMXNode.cpp @@ -49,8 +49,10 @@ public: } // namespace -C2OMXNode::C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp) - : mComp(comp), mFrameIndex(0), mWidth(0), mHeight(0), +C2OMXNode::C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp, + const std::shared_ptr<InputGater> &inputGater) + : mComp(comp), mInputGater(inputGater), + mFrameIndex(0), mWidth(0), mHeight(0), mAdjustTimestampGapUs(0), mFirstInputFrame(true) { // TODO: read from intf() if (!strncmp(comp->getName().c_str(), "c2.android.", 11)) { @@ -212,6 +214,7 @@ status_t C2OMXNode::emptyBuffer( sp<Fence> fence = new Fence(fenceFd); fence->waitForever(LOG_TAG); } + std::shared_ptr<Codec2Client::Component> comp = mComp.lock(); if (!comp) { return NO_INIT; @@ -287,6 +290,11 @@ status_t C2OMXNode::emptyBuffer( std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); + std::shared_ptr<InputGater> inputGater = mInputGater.lock(); + if (!inputGater || !inputGater->canQueue()) { + return OK; + } + c2_status_t err = comp->queue(&items); if (err != C2_OK) { return UNKNOWN_ERROR; diff --git a/media/sfplugin/C2OMXNode.h b/media/sfplugin/C2OMXNode.h index b5a815e..a81a993 100644 --- a/media/sfplugin/C2OMXNode.h +++ b/media/sfplugin/C2OMXNode.h @@ -24,6 +24,8 @@ #include <media/OMXBuffer.h> #include <codec2/hidl/client.h> +#include "InputSurfaceWrapper.h" + namespace android { /** @@ -33,7 +35,12 @@ namespace android { * to work in any other usage than IGraphicBufferSource. */ struct C2OMXNode : public BnOMXNode { - explicit C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp); + + using InputGater = InputSurfaceWrapper::InputGater; + + explicit C2OMXNode( + const std::shared_ptr<Codec2Client::Component> &comp, + const std::shared_ptr<InputGater> &inputGater); ~C2OMXNode() override = default; // IOMXNode @@ -80,6 +87,7 @@ struct C2OMXNode : public BnOMXNode { private: std::weak_ptr<Codec2Client::Component> mComp; + std::weak_ptr<InputGater> mInputGater; sp<IOMXBufferSource> mBufferSource; std::shared_ptr<C2Allocator> mAllocator; std::atomic_uint64_t mFrameIndex; diff --git a/media/sfplugin/CCodec.cpp b/media/sfplugin/CCodec.cpp index 20c3de3..e370edd 100644 --- a/media/sfplugin/CCodec.cpp +++ b/media/sfplugin/CCodec.cpp @@ -139,7 +139,8 @@ public: ~C2InputSurfaceWrapper() override = default; - status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override { + status_t connect(const std::shared_ptr<Codec2Client::Component> &comp, + const std::shared_ptr<InputGater>& /*inputGater*/) override { if (mConnection != nullptr) { return ALREADY_EXISTS; } @@ -191,8 +192,9 @@ public: } ~GraphicBufferSourceWrapper() override = default; - status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override { - mNode = new C2OMXNode(comp); + status_t connect(const std::shared_ptr<Codec2Client::Component> &comp, + const std::shared_ptr<InputGater> &inputGater) override { + mNode = new C2OMXNode(comp, inputGater); mNode->setFrameSize(mWidth, mHeight); // NOTE: we do not use/pass through color aspects from GraphicBufferSource as we @@ -373,6 +375,7 @@ private: sp<C2OMXNode> mNode; uint32_t mWidth; uint32_t mHeight; + std::shared_ptr<C2OMXNode::InputGater> mInputGater; Config mConfig; }; diff --git a/media/sfplugin/CCodecBufferChannel.cpp b/media/sfplugin/CCodecBufferChannel.cpp index 2cdea6e..d6d6d68 100644 --- a/media/sfplugin/CCodecBufferChannel.cpp +++ b/media/sfplugin/CCodecBufferChannel.cpp @@ -1428,6 +1428,31 @@ bool CCodecBufferChannel::PipelineCapacity::allocate(const char* callerTag) { return false; } +bool CCodecBufferChannel::PipelineCapacity::allocateOutput(const char* callerTag) { + int prevComponent = component.fetch_sub(1, std::memory_order_relaxed); + int prevOutput = output.fetch_sub(1, std::memory_order_relaxed); + if (prevComponent > 0 && prevOutput > 1) { // One output reserved for csd. + ALOGV("[%s] %s -- PipelineCapacity::allocateOutput() returns true: " + "pipeline availability -1 output and -1 component ==> " + "input = %d, component = %d, output = %d", + mName, callerTag ? callerTag : "*", + input.load(std::memory_order_relaxed), + prevComponent - 1, + prevOutput - 1); + return true; + } + component.fetch_add(1, std::memory_order_relaxed); + output.fetch_add(1, std::memory_order_relaxed); + ALOGV("[%s] %s -- PipelineCapacity::allocateOutput() returns false: " + "pipeline availability unchanged ==> " + "input = %d, component = %d, output = %d", + mName, callerTag ? callerTag : "*", + input.load(std::memory_order_relaxed), + prevComponent, + prevOutput); + return false; +} + void CCodecBufferChannel::PipelineCapacity::free(const char* callerTag) { int prevInput = input.fetch_add(1, std::memory_order_relaxed); int prevComponent = component.fetch_add(1, std::memory_order_relaxed); @@ -1484,6 +1509,23 @@ int CCodecBufferChannel::PipelineCapacity::freeOutputSlot( return prevOutput + 1; } +// InputGater +struct CCodecBufferChannel::InputGater : public InputSurfaceWrapper::InputGater { + InputGater(const std::shared_ptr<CCodecBufferChannel>& owner) + : mOwner(owner) {} + virtual bool canQueue() override { + std::shared_ptr<CCodecBufferChannel> owner = mOwner.lock(); + if (!owner) { + return false; + } + QueueGuard guard(owner->mSync); + return guard.isRunning() && + owner->mAvailablePipelineCapacity.allocateOutput("InputGater"); + } +private: + std::weak_ptr<CCodecBufferChannel> mOwner; +}; + // CCodecBufferChannel CCodecBufferChannel::CCodecBufferChannel( @@ -1517,7 +1559,8 @@ status_t CCodecBufferChannel::setInputSurface( const std::shared_ptr<InputSurfaceWrapper> &surface) { ALOGV("[%s] setInputSurface", mName); mInputSurface = surface; - return mInputSurface->connect(mComponent); + mInputGater = std::make_shared<InputGater>(shared_from_this()); + return mInputSurface->connect(mComponent, mInputGater); } status_t CCodecBufferChannel::signalEndOfInputStream() { @@ -2318,6 +2361,7 @@ void CCodecBufferChannel::stop() { if (mInputSurface != nullptr) { mInputSurface.reset(); } + mInputGater.reset(); } void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) { diff --git a/media/sfplugin/CCodecBufferChannel.h b/media/sfplugin/CCodecBufferChannel.h index 86739ab..3ef58be 100644 --- a/media/sfplugin/CCodecBufferChannel.h +++ b/media/sfplugin/CCodecBufferChannel.h @@ -308,6 +308,18 @@ private: // onInputBufferAvailable() can (and will) be called afterwards. bool allocate(const char* callerTag = nullptr); + // Return true and decrease #component and #output by one if they are + // all greater than zero; return false otherwise. + // + // callerTag is used for logging only. + // + // allocateOutput() is called by CCodecBufferChannel::InputGater to + // check whether the component can accept a queue operation. This is + // used when the input comes from an input surface rather than from + // queueInputBuffer(). Calling allocateOutput() is similar to calling + // allocate() when the input capacity is infinite. + bool allocateOutput(const char* callerTag = nullptr); + // Increase #input, #component and #output by one. // // callerTag is used for logging only. @@ -356,6 +368,9 @@ private: inline bool hasCryptoOrDescrambler() { return mCrypto != NULL || mDescrambler != NULL; } + + struct InputGater; + std::shared_ptr<InputGater> mInputGater; }; // Conversion of a c2_status_t value to a status_t value may depend on the diff --git a/media/sfplugin/InputSurfaceWrapper.h b/media/sfplugin/InputSurfaceWrapper.h index d9c4eec..12e58b2 100644 --- a/media/sfplugin/InputSurfaceWrapper.h +++ b/media/sfplugin/InputSurfaceWrapper.h @@ -33,15 +33,33 @@ public: virtual ~InputSurfaceWrapper() = default; + struct InputGater { + /** + * Try to reserve an input in the pipeline. If this function returns + * true, the pipeline slot is reserved. An implementation of + * InputSurfaceWrapper should not call Component::queue() if canQueue() + * returns false. + * + * \return true if the input can be reserved; false otherwise. + */ + virtual bool canQueue() = 0; + virtual ~InputGater() = default; + }; + /** * Connect the surface with |comp|. A surface can * connect to at most one component at a time. * + * `inputGater->canQueue()` will be called before queuing a buffer. If it + * returns false, the buffer will not be queued to `comp` and simply + * dropped. + * * \return OK successfully connected to |comp| * \return ALREADY_EXISTS already connected to another component. */ virtual status_t connect( - const std::shared_ptr<Codec2Client::Component> &comp) = 0; + const std::shared_ptr<Codec2Client::Component> &comp, + const std::shared_ptr<InputGater> &inputGater) = 0; /** * Disconnect the surface from the component if any. |