Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acee494a authored by Wonsik Kim's avatar Wonsik Kim Committed by Android (Google) Code Review
Browse files

Merge "stagefright: MediaCodec buffer API revision"

parents 7bdf12b1 fb7a7671
Loading
Loading
Loading
Loading
+255 −2
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@
#include "C2OMXNode.h"
#include "CCodecBufferChannel.h"
#include "CCodecConfig.h"
#include "Codec2Mapper.h"
#include "InputSurfaceWrapper.h"

extern "C" android::PersistentSurface *CreateInputSurface();
@@ -717,6 +718,11 @@ void CCodec::configure(const sp<AMessage> &msg) {
            encoder = false;
        }

        int32_t flags;
        if (!msg->findInt32("flags", &flags)) {
            return BAD_VALUE;
        }

        // TODO: read from intf()
        if ((!encoder) != (comp->getName().find("encoder") == std::string::npos)) {
            return UNKNOWN_ERROR;
@@ -743,6 +749,9 @@ void CCodec::configure(const sp<AMessage> &msg) {
        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
        const std::unique_ptr<Config> &config = *configLocked;
        config->mUsingSurface = surface != nullptr;
        config->mBuffersBoundToCodec = ((flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) == 0);
        ALOGD("[%s] buffers are %sbound to CCodec for this session",
              comp->getName().c_str(), config->mBuffersBoundToCodec ? "" : "not ");

        // Enforce required parameters
        int32_t i32;
@@ -1299,6 +1308,7 @@ void CCodec::start() {
    sp<AMessage> inputFormat;
    sp<AMessage> outputFormat;
    status_t err2 = OK;
    bool buffersBoundToCodec = false;
    {
        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
        const std::unique_ptr<Config> &config = *configLocked;
@@ -1307,12 +1317,13 @@ void CCodec::start() {
        if (config->mInputSurface) {
            err2 = config->mInputSurface->start();
        }
        buffersBoundToCodec = config->mBuffersBoundToCodec;
    }
    if (err2 != OK) {
        mCallback->onError(err2, ACTION_CODE_FATAL);
        return;
    }
    err2 = mChannel->start(inputFormat, outputFormat);
    err2 = mChannel->start(inputFormat, outputFormat, buffersBoundToCodec);
    if (err2 != OK) {
        mCallback->onError(err2, ACTION_CODE_FATAL);
        return;
@@ -1556,7 +1567,11 @@ void CCodec::signalResume() {
        return;
    }

    (void)mChannel->start(nullptr, nullptr);
    (void)mChannel->start(nullptr, nullptr, [&]{
        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
        const std::unique_ptr<Config> &config = *configLocked;
        return config->mBuffersBoundToCodec;
    }());

    {
        Mutexed<State>::Locked state(mState);
@@ -1911,5 +1926,243 @@ PersistentSurface *CCodec::CreateInputSurface() {
            inputSurface->getHalInterface()));
}

static status_t GetCommonAllocatorIds(
        const std::vector<std::string> &names,
        C2Allocator::type_t type,
        std::set<C2Allocator::id_t> *ids) {
    int poolMask = GetCodec2PoolMask();
    C2PlatformAllocatorStore::id_t preferredLinearId = GetPreferredLinearAllocatorId(poolMask);
    C2Allocator::id_t defaultAllocatorId =
        (type == C2Allocator::LINEAR) ? preferredLinearId : C2PlatformAllocatorStore::GRALLOC;

    ids->clear();
    if (names.empty()) {
        return OK;
    }
    std::shared_ptr<Codec2Client::Interface> intf{
        Codec2Client::CreateInterfaceByName(names[0].c_str())};
    std::vector<std::unique_ptr<C2Param>> params;
    c2_status_t err = intf->query(
            {}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, &params);
    if (err == C2_OK && params.size() == 1u) {
        C2PortAllocatorsTuning::input *allocators =
            C2PortAllocatorsTuning::input::From(params[0].get());
        if (allocators && allocators->flexCount() > 0) {
            ids->insert(allocators->m.values, allocators->m.values + allocators->flexCount());
        }
    }
    if (ids->empty()) {
        // The component does not advertise allocators. Use default.
        ids->insert(defaultAllocatorId);
    }
    for (size_t i = 1; i < names.size(); ++i) {
        intf = Codec2Client::CreateInterfaceByName(names[i].c_str());
        err = intf->query(
                {}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, &params);
        bool filtered = false;
        if (err == C2_OK && params.size() == 1u) {
            C2PortAllocatorsTuning::input *allocators =
                C2PortAllocatorsTuning::input::From(params[0].get());
            if (allocators && allocators->flexCount() > 0) {
                filtered = true;
                for (auto it = ids->begin(); it != ids->end(); ) {
                    bool found = false;
                    for (size_t j = 0; j < allocators->flexCount(); ++j) {
                        if (allocators->m.values[j] == *it) {
                            found = true;
                            break;
                        }
                    }
                    if (found) {
                        ++it;
                    } else {
                        it = ids->erase(it);
                    }
                }
            }
        }
        if (!filtered) {
            // The component does not advertise supported allocators. Use default.
            bool containsDefault = (ids->count(defaultAllocatorId) > 0u);
            if (ids->size() != (containsDefault ? 1 : 0)) {
                ids->clear();
                if (containsDefault) {
                    ids->insert(defaultAllocatorId);
                }
            }
        }
    }
    // Finally, filter with pool masks
    for (auto it = ids->begin(); it != ids->end(); ) {
        if ((poolMask >> *it) & 1) {
            ++it;
        } else {
            it = ids->erase(it);
        }
    }
    return OK;
}

static status_t CalculateMinMaxUsage(
        const std::vector<std::string> &names, uint64_t *minUsage, uint64_t *maxUsage) {
    static C2StreamUsageTuning::input sUsage{0u /* stream id */};
    *minUsage = 0;
    *maxUsage = ~0ull;
    for (const std::string &name : names) {
        std::shared_ptr<Codec2Client::Interface> intf{
            Codec2Client::CreateInterfaceByName(name.c_str())};
        std::vector<C2FieldSupportedValuesQuery> fields;
        fields.push_back(C2FieldSupportedValuesQuery::Possible(
                C2ParamField{&sUsage, &sUsage.value}));
        c2_status_t err = intf->querySupportedValues(fields, C2_MAY_BLOCK);
        if (err != C2_OK) {
            continue;
        }
        if (fields[0].status != C2_OK) {
            continue;
        }
        const C2FieldSupportedValues &supported = fields[0].values;
        if (supported.type != C2FieldSupportedValues::FLAGS) {
            continue;
        }
        if (supported.values.empty()) {
            *maxUsage = 0;
            continue;
        }
        *minUsage |= supported.values[0].u64;
        int64_t currentMaxUsage = 0;
        for (const C2Value::Primitive &flags : supported.values) {
            currentMaxUsage |= flags.u64;
        }
        *maxUsage &= currentMaxUsage;
    }
    return OK;
}

// static
status_t CCodec::CanFetchLinearBlock(
        const std::vector<std::string> &names, const C2MemoryUsage &usage, bool *isCompatible) {
    uint64_t minUsage = usage.expected;
    uint64_t maxUsage = ~0ull;
    std::set<C2Allocator::id_t> allocators;
    GetCommonAllocatorIds(names, C2Allocator::LINEAR, &allocators);
    if (allocators.empty()) {
        *isCompatible = false;
        return OK;
    }
    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
    *isCompatible = ((maxUsage & minUsage) == minUsage);
    return OK;
}

static std::shared_ptr<C2BlockPool> GetPool(C2Allocator::id_t allocId) {
    static std::mutex sMutex{};
    static std::map<C2Allocator::id_t, std::shared_ptr<C2BlockPool>> sPools;
    std::unique_lock<std::mutex> lock{sMutex};
    std::shared_ptr<C2BlockPool> pool;
    auto it = sPools.find(allocId);
    if (it == sPools.end()) {
        c2_status_t err = CreateCodec2BlockPool(allocId, nullptr, &pool);
        if (err == OK) {
            sPools.emplace(allocId, pool);
        } else {
            pool.reset();
        }
    } else {
        pool = it->second;
    }
    return pool;
}

// static
std::shared_ptr<C2LinearBlock> CCodec::FetchLinearBlock(
        size_t capacity, const C2MemoryUsage &usage, const std::vector<std::string> &names) {
    uint64_t minUsage = usage.expected;
    uint64_t maxUsage = ~0ull;
    std::set<C2Allocator::id_t> allocators;
    GetCommonAllocatorIds(names, C2Allocator::LINEAR, &allocators);
    if (allocators.empty()) {
        allocators.insert(C2PlatformAllocatorStore::DEFAULT_LINEAR);
    }
    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
    if ((maxUsage & minUsage) != minUsage) {
        allocators.clear();
        allocators.insert(C2PlatformAllocatorStore::DEFAULT_LINEAR);
    }
    std::shared_ptr<C2LinearBlock> block;
    for (C2Allocator::id_t allocId : allocators) {
        std::shared_ptr<C2BlockPool> pool = GetPool(allocId);
        if (!pool) {
            continue;
        }
        c2_status_t err = pool->fetchLinearBlock(capacity, C2MemoryUsage{minUsage}, &block);
        if (err != C2_OK || !block) {
            block.reset();
            continue;
        }
        break;
    }
    return block;
}

// static
status_t CCodec::CanFetchGraphicBlock(
        const std::vector<std::string> &names, bool *isCompatible) {
    uint64_t minUsage = 0;
    uint64_t maxUsage = ~0ull;
    std::set<C2Allocator::id_t> allocators;
    GetCommonAllocatorIds(names, C2Allocator::GRAPHIC, &allocators);
    if (allocators.empty()) {
        *isCompatible = false;
        return OK;
    }
    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
    *isCompatible = ((maxUsage & minUsage) == minUsage);
    return OK;
}

// static
std::shared_ptr<C2GraphicBlock> CCodec::FetchGraphicBlock(
        int32_t width,
        int32_t height,
        int32_t format,
        uint64_t usage,
        const std::vector<std::string> &names) {
    uint32_t halPixelFormat = HAL_PIXEL_FORMAT_YCBCR_420_888;
    if (!C2Mapper::mapPixelFormatFrameworkToCodec(format, &halPixelFormat)) {
        ALOGD("Unrecognized pixel format: %d", format);
        return nullptr;
    }
    uint64_t minUsage = 0;
    uint64_t maxUsage = ~0ull;
    std::set<C2Allocator::id_t> allocators;
    GetCommonAllocatorIds(names, C2Allocator::GRAPHIC, &allocators);
    if (allocators.empty()) {
        allocators.insert(C2PlatformAllocatorStore::DEFAULT_GRAPHIC);
    }
    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
    minUsage |= usage;
    if ((maxUsage & minUsage) != minUsage) {
        allocators.clear();
        allocators.insert(C2PlatformAllocatorStore::DEFAULT_GRAPHIC);
    }
    std::shared_ptr<C2GraphicBlock> block;
    for (C2Allocator::id_t allocId : allocators) {
        std::shared_ptr<C2BlockPool> pool;
        c2_status_t err = CreateCodec2BlockPool(allocId, nullptr, &pool);
        if (err != C2_OK || !pool) {
            continue;
        }
        err = pool->fetchGraphicBlock(
                width, height, halPixelFormat, C2MemoryUsage{minUsage}, &block);
        if (err != C2_OK || !block) {
            block.reset();
            continue;
        }
        break;
    }
    return block;
}

}  // namespace android
+186 −4
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/drm/1.0/types.h>
#include <android-base/stringprintf.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryDealer.h>
#include <cutils/properties.h>
#include <gui/Surface.h>
@@ -249,7 +250,7 @@ CCodecBufferChannel::CCodecBufferChannel(
}

CCodecBufferChannel::~CCodecBufferChannel() {
    if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
    if (mCrypto != nullptr && mHeapSeqNum >= 0) {
        mCrypto->unsetHeap(mHeapSeqNum);
    }
}
@@ -409,6 +410,173 @@ status_t CCodecBufferChannel::setParameters(std::vector<std::unique_ptr<C2Param>
    return OK;
}

status_t CCodecBufferChannel::attachBuffer(
        const std::shared_ptr<C2Buffer> &c2Buffer,
        const sp<MediaCodecBuffer> &buffer) {
    if (!buffer->copy(c2Buffer)) {
        return -ENOSYS;
    }
    return OK;
}

void CCodecBufferChannel::ensureDecryptDestination(size_t size) {
    if (!mDecryptDestination || mDecryptDestination->size() < size) {
        sp<IMemoryHeap> heap{new MemoryHeapBase(size * 2)};
        if (mDecryptDestination && mCrypto && mHeapSeqNum >= 0) {
            mCrypto->unsetHeap(mHeapSeqNum);
        }
        mDecryptDestination = new MemoryBase(heap, 0, size * 2);
        if (mCrypto) {
            mHeapSeqNum = mCrypto->setHeap(hardware::fromHeap(heap));
        }
    }
}

int32_t CCodecBufferChannel::getHeapSeqNum(const sp<HidlMemory> &memory) {
    CHECK(mCrypto);
    auto it = mHeapSeqNumMap.find(memory);
    int32_t heapSeqNum = -1;
    if (it == mHeapSeqNumMap.end()) {
        heapSeqNum = mCrypto->setHeap(memory);
        mHeapSeqNumMap.emplace(memory, heapSeqNum);
    } else {
        heapSeqNum = it->second;
    }
    return heapSeqNum;
}

status_t CCodecBufferChannel::attachEncryptedBuffer(
        const sp<hardware::HidlMemory> &memory,
        bool secure,
        const uint8_t *key,
        const uint8_t *iv,
        CryptoPlugin::Mode mode,
        CryptoPlugin::Pattern pattern,
        size_t offset,
        const CryptoPlugin::SubSample *subSamples,
        size_t numSubSamples,
        const sp<MediaCodecBuffer> &buffer) {
    static const C2MemoryUsage kSecureUsage{C2MemoryUsage::READ_PROTECTED, 0};
    static const C2MemoryUsage kDefaultReadWriteUsage{
        C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};

    size_t size = 0;
    for (size_t i = 0; i < numSubSamples; ++i) {
        size += subSamples[i].mNumBytesOfClearData + subSamples[i].mNumBytesOfEncryptedData;
    }
    std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool;
    std::shared_ptr<C2LinearBlock> block;
    c2_status_t err = pool->fetchLinearBlock(
            size,
            secure ? kSecureUsage : kDefaultReadWriteUsage,
            &block);
    if (err != C2_OK) {
        return NO_MEMORY;
    }
    if (!secure) {
        ensureDecryptDestination(size);
    }
    ssize_t result = -1;
    ssize_t codecDataOffset = 0;
    if (mCrypto) {
        AString errorDetailMsg;
        int32_t heapSeqNum = getHeapSeqNum(memory);
        hardware::drm::V1_0::SharedBuffer src{(uint32_t)heapSeqNum, offset, size};
        hardware::drm::V1_0::DestinationBuffer dst;
        if (secure) {
            dst.type = DrmBufferType::NATIVE_HANDLE;
            dst.secureMemory = hardware::hidl_handle(block->handle());
        } else {
            dst.type = DrmBufferType::SHARED_MEMORY;
            IMemoryToSharedBuffer(
                    mDecryptDestination, mHeapSeqNum, &dst.nonsecureMemory);
        }
        result = mCrypto->decrypt(
                key, iv, mode, pattern, src, 0, subSamples, numSubSamples,
                dst, &errorDetailMsg);
        if (result < 0) {
            return result;
        }
        if (dst.type == DrmBufferType::SHARED_MEMORY) {
            C2WriteView view = block->map().get();
            if (view.error() != C2_OK) {
                return false;
            }
            if (view.size() < result) {
                return false;
            }
            memcpy(view.data(), mDecryptDestination->unsecurePointer(), result);
        }
    } else {
        // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
        // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
        hidl_vec<SubSample> hidlSubSamples;
        hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);

        hardware::cas::native::V1_0::SharedBuffer src{*memory, offset, size};
        hardware::cas::native::V1_0::DestinationBuffer dst;
        if (secure) {
            dst.type = BufferType::NATIVE_HANDLE;
            dst.secureMemory = hardware::hidl_handle(block->handle());
        } else {
            dst.type = BufferType::SHARED_MEMORY;
            dst.nonsecureMemory = src;
        }

        CasStatus status = CasStatus::OK;
        hidl_string detailedError;
        ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED;

        if (key != nullptr) {
            sctrl = (ScramblingControl)key[0];
            // Adjust for the PES offset
            codecDataOffset = key[2] | (key[3] << 8);
        }

        auto returnVoid = mDescrambler->descramble(
                sctrl,
                hidlSubSamples,
                src,
                0,
                dst,
                0,
                [&status, &result, &detailedError] (
                        CasStatus _status, uint32_t _bytesWritten,
                        const hidl_string& _detailedError) {
                    status = _status;
                    result = (ssize_t)_bytesWritten;
                    detailedError = _detailedError;
                });

        if (!returnVoid.isOk() || status != CasStatus::OK || result < 0) {
            ALOGI("[%s] descramble failed, trans=%s, status=%d, result=%zd",
                    mName, returnVoid.description().c_str(), status, result);
            return UNKNOWN_ERROR;
        }

        if (result < codecDataOffset) {
            ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result);
            return BAD_VALUE;
        }
    }
    if (!secure) {
        C2WriteView view = block->map().get();
        if (view.error() != C2_OK) {
            return UNKNOWN_ERROR;
        }
        if (view.size() < result) {
            return UNKNOWN_ERROR;
        }
        memcpy(view.data(), mDecryptDestination->unsecurePointer(), result);
    }
    std::shared_ptr<C2Buffer> c2Buffer{C2Buffer::CreateLinearBuffer(
            block->share(codecDataOffset, result - codecDataOffset, C2Fence{}))};
    if (!buffer->copy(c2Buffer)) {
        return -ENOSYS;
    }
    return OK;
}

status_t CCodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
    QueueGuard guard(mSync);
    if (!guard.isRunning()) {
@@ -774,7 +942,9 @@ void CCodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *arr
}

status_t CCodecBufferChannel::start(
        const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
        const sp<AMessage> &inputFormat,
        const sp<AMessage> &outputFormat,
        bool buffersBoundToCodec) {
    C2StreamBufferTypeSetting::input iStreamFormat(0u);
    C2StreamBufferTypeSetting::output oStreamFormat(0u);
    C2PortReorderBufferDepthTuning::output reorderDepth;
@@ -897,7 +1067,9 @@ status_t CCodecBufferChannel::start(
        input->numSlots = numInputSlots;
        input->extraBuffers.flush();
        input->numExtraSlots = 0u;
        if (graphic) {
        if (!buffersBoundToCodec) {
            input->buffers.reset(new SlotInputBuffers(mName));
        } else if (graphic) {
            if (mInputSurface) {
                input->buffers.reset(new DummyInputBuffers(mName));
            } else if (mMetaMode == MODE_ANW) {
@@ -1071,7 +1243,7 @@ status_t CCodecBufferChannel::start(
        output->outputDelay = outputDelayValue;
        output->numSlots = numOutputSlots;
        if (graphic) {
            if (outputSurface) {
            if (outputSurface || !buffersBoundToCodec) {
                output->buffers.reset(new GraphicOutputBuffers(mName));
            } else {
                output->buffers.reset(new RawGraphicOutputBuffers(numOutputSlots, mName));
@@ -1669,6 +1841,16 @@ void CCodecBufferChannel::setMetaMode(MetaMode mode) {
}

void CCodecBufferChannel::setCrypto(const sp<ICrypto> &crypto) {
    if (mCrypto != nullptr) {
        for (std::pair<wp<HidlMemory>, int32_t> entry : mHeapSeqNumMap) {
            mCrypto->unsetHeap(entry.second);
        }
        mHeapSeqNumMap.clear();
        if (mHeapSeqNum >= 0) {
            mCrypto->unsetHeap(mHeapSeqNum);
            mHeapSeqNum = -1;
        }
    }
    mCrypto = crypto;
}

+21 −1
Original line number Diff line number Diff line
@@ -70,6 +70,20 @@ public:
            const CryptoPlugin::SubSample *subSamples,
            size_t numSubSamples,
            AString *errorDetailMsg) override;
    virtual status_t attachBuffer(
            const std::shared_ptr<C2Buffer> &c2Buffer,
            const sp<MediaCodecBuffer> &buffer) override;
    virtual status_t attachEncryptedBuffer(
            const sp<hardware::HidlMemory> &memory,
            bool secure,
            const uint8_t *key,
            const uint8_t *iv,
            CryptoPlugin::Mode mode,
            CryptoPlugin::Pattern pattern,
            size_t offset,
            const CryptoPlugin::SubSample *subSamples,
            size_t numSubSamples,
            const sp<MediaCodecBuffer> &buffer) override;
    virtual status_t renderOutputBuffer(
            const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
    virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
@@ -108,7 +122,10 @@ public:
     * Start queueing buffers to the component. This object should never queue
     * buffers before this call has completed.
     */
    status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat);
    status_t start(
            const sp<AMessage> &inputFormat,
            const sp<AMessage> &outputFormat,
            bool buffersBoundToCodec);

    /**
     * Request initial input buffers to be filled by client.
@@ -216,11 +233,14 @@ private:
            std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
            const C2StreamInitDataInfo::output *initData);
    void sendOutputBuffers();
    void ensureDecryptDestination(size_t size);
    int32_t getHeapSeqNum(const sp<hardware::HidlMemory> &memory);

    QueueSync mSync;
    sp<MemoryDealer> mDealer;
    sp<IMemory> mDecryptDestination;
    int32_t mHeapSeqNum;
    std::map<wp<hardware::HidlMemory>, int32_t> mHeapSeqNumMap;

    std::shared_ptr<Codec2Client::Component> mComponent;
    std::string mComponentName; ///< component name for debugging
+38 −0
Original line number Diff line number Diff line
@@ -494,6 +494,44 @@ sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
    return mAllocate();
}

// SlotInputBuffers

bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
    sp<Codec2Buffer> newBuffer = createNewBuffer();
    *index = mImpl.assignSlot(newBuffer);
    *buffer = newBuffer;
    return true;
}

bool SlotInputBuffers::releaseBuffer(
        const sp<MediaCodecBuffer> &buffer,
        std::shared_ptr<C2Buffer> *c2buffer,
        bool release) {
    return mImpl.releaseSlot(buffer, c2buffer, release);
}

bool SlotInputBuffers::expireComponentBuffer(
        const std::shared_ptr<C2Buffer> &c2buffer) {
    return mImpl.expireComponentBuffer(c2buffer);
}

void SlotInputBuffers::flush() {
    mImpl.flush();
}

std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
    TRESPASS("Array mode should not be called at non-legacy mode");
    return nullptr;
}

size_t SlotInputBuffers::numClientBuffers() const {
    return mImpl.numClientBuffers();
}

sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
    return new DummyContainerBuffer{mFormat, nullptr};
}

// LinearInputBuffers

bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
+30 −0
Original line number Diff line number Diff line
@@ -547,6 +547,36 @@ private:
    std::function<sp<Codec2Buffer>()> mAllocate;
};

class SlotInputBuffers : public InputBuffers {
public:
    SlotInputBuffers(const char *componentName, const char *name = "Slot-Input")
        : InputBuffers(componentName, name),
          mImpl(mName) { }
    ~SlotInputBuffers() override = default;

    bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) final;

    bool releaseBuffer(
            const sp<MediaCodecBuffer> &buffer,
            std::shared_ptr<C2Buffer> *c2buffer,
            bool release) final;

    bool expireComponentBuffer(
            const std::shared_ptr<C2Buffer> &c2buffer) final;

    void flush() final;

    std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;

    size_t numClientBuffers() const final;

protected:
    sp<Codec2Buffer> createNewBuffer() final;

private:
    FlexBuffersImpl mImpl;
};

class LinearInputBuffers : public InputBuffers {
public:
    LinearInputBuffers(const char *componentName, const char *name = "1D-Input")
Loading