diff --git a/content/media/omx/MediaCodecProxy.cpp b/content/media/omx/MediaCodecProxy.cpp index 8ad5f14f996c..3606d22d0ff5 100644 --- a/content/media/omx/MediaCodecProxy.cpp +++ b/content/media/omx/MediaCodecProxy.cpp @@ -18,6 +18,62 @@ #define TIMEOUT_DEQUEUE_INPUTBUFFER_MS 1000000ll namespace android { +// General Template: MediaCodec::getOutputGraphicBufferFromIndex(...) +template +struct OutputGraphicBufferStub +{ + static status_t GetOutputGraphicBuffer(T *aMediaCodec, + size_t aIndex, + sp *aGraphicBuffer) + { + return ERROR_UNSUPPORTED; + } +}; + +// Class Template Specialization: MediaCodec::getOutputGraphicBufferFromIndex(...) +template +struct OutputGraphicBufferStub +{ + static status_t GetOutputGraphicBuffer(T *aMediaCodec, + size_t aIndex, + sp *aGraphicBuffer) + { + if (aMediaCodec == nullptr || aGraphicBuffer == nullptr) { + return BAD_VALUE; + } + *aGraphicBuffer = aMediaCodec->getOutputGraphicBufferFromIndex(aIndex); + return OK; + } +}; + +// Wrapper class to handle interface-difference of MediaCodec. +struct MediaCodecInterfaceWrapper +{ + typedef int8_t Supported; + typedef int16_t Unsupported; + + template + static auto TestOutputGraphicBuffer(T *aMediaCodec) -> decltype(aMediaCodec->getOutputGraphicBufferFromIndex(0), Supported()); + + template + static auto TestOutputGraphicBuffer(...) -> Unsupported; + + // SFINAE: Substitution Failure Is Not An Error + static const bool OutputGraphicBufferSupported = sizeof(TestOutputGraphicBuffer(nullptr)) == sizeof(Supported); + + // Class Template Specialization + static OutputGraphicBufferStub sOutputGraphicBufferStub; + + // Wrapper Function + static status_t GetOutputGraphicBuffer(MediaCodec *aMediaCodec, + size_t aIndex, + sp *aGraphicBuffer) + { + return sOutputGraphicBufferStub.GetOutputGraphicBuffer(aMediaCodec, aIndex, aGraphicBuffer); + } + +}; + sp MediaCodecProxy::CreateByType(sp aLooper, const char *aMime, @@ -363,6 +419,37 @@ MediaCodecProxy::requestActivityNotification(const sp &aNotify) mCodec->requestActivityNotification(aNotify); } +status_t +MediaCodecProxy::getOutputGraphicBufferFromIndex(size_t aIndex, + sp *aGraphicBuffer) +{ + // Read Lock for mCodec + RWLock::AutoRLock arl(mCodecLock); + + if (mCodec == nullptr) { + return NO_INIT; + } + return MediaCodecInterfaceWrapper::GetOutputGraphicBuffer(mCodec.get(), aIndex, aGraphicBuffer); +} + +status_t +MediaCodecProxy::getCapability(uint32_t *aCapability) +{ + if (aCapability == nullptr) { + return BAD_VALUE; + } + + uint32_t capability = kEmptyCapability; + + if (MediaCodecInterfaceWrapper::OutputGraphicBufferSupported) { + capability |= kCanExposeGraphicBuffer; + } + + *aCapability = capability; + + return OK; +} + // Called on a Binder thread void MediaCodecProxy::resourceReserved() diff --git a/content/media/omx/MediaCodecProxy.h b/content/media/omx/MediaCodecProxy.h index 828fc30108c7..6f8d5f4a6b98 100644 --- a/content/media/omx/MediaCodecProxy.h +++ b/content/media/omx/MediaCodecProxy.h @@ -40,9 +40,15 @@ public: virtual void codecCanceled() = 0; }; + enum Capability { + kEmptyCapability = 0x00000000, + kCanExposeGraphicBuffer = 0x00000001, + }; + enum { kKeyBufferIndex = 'bfin', }; + // Check whether MediaCodec has been allocated. bool allocated() const; @@ -112,6 +118,14 @@ public: // an input/output buffer has become available, a format change is // pending, an error is pending. void requestActivityNotification(const sp &aNotify); + + status_t getOutputGraphicBufferFromIndex(size_t aIndex, + sp *aGraphicBuffer); + + status_t getCapability(uint32_t *aCapability); + + // Utility functions + // If aData is null, will notify decoder input EOS status_t Input(const uint8_t* aData, uint32_t aDataSize, int64_t aTimestampUsecs, uint64_t flags); @@ -120,6 +134,7 @@ public: bool IsWaitingResources(); bool IsDormantNeeded(); void ReleaseMediaResources(); + protected: virtual ~MediaCodecProxy(); @@ -165,6 +180,7 @@ private: // MediaCodec instance mutable RWLock mCodecLock; sp mCodec; + //MediaCodec buffers to hold input/output data. Vector > mInputBuffers; Vector > mOutputBuffers;