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

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

Merge "codec2: add C2SoftAac"

parents 4ca35070 ccebc2cb
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -42,7 +42,10 @@ cc_library_shared {
        "optional",
    ],

    srcs: ["SimpleC2Component.cpp"],
    srcs: [
        "SimpleC2Component.cpp",
        "SimpleC2Interface.cpp",
    ],

    include_dirs: [
    ],
+138 −32
Original line number Diff line number Diff line
@@ -18,12 +18,39 @@
#define LOG_TAG "SimpleC2Component"
#include <media/stagefright/foundation/ADebug.h>

#include <C2PlatformSupport.h>
#include <inttypes.h>

#include <C2PlatformSupport.h>
#include <SimpleC2Component.h>

namespace android {

std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() {
    std::unique_ptr<C2Work> work = std::move(mQueue.front().work);
    mQueue.pop_front();
    return work;
}

void SimpleC2Component::WorkQueue::push_back(std::unique_ptr<C2Work> work) {
    mQueue.push_back({ std::move(work), NO_DRAIN });
}

bool SimpleC2Component::WorkQueue::empty() const {
    return mQueue.empty();
}

void SimpleC2Component::WorkQueue::clear() {
    mQueue.clear();
}

uint32_t SimpleC2Component::WorkQueue::drainMode() const {
    return mQueue.front().drainMode;
}

void SimpleC2Component::WorkQueue::markDrain(uint32_t drainMode) {
    mQueue.push_back({ nullptr, drainMode });
}

SimpleC2Component::SimpleC2Component(
        const std::shared_ptr<C2ComponentInterface> &intf)
    : mIntf(intf) {
@@ -55,7 +82,7 @@ c2_status_t SimpleC2Component::queue_nb(std::list<std::unique_ptr<C2Work>> * con
    {
        Mutexed<WorkQueue>::Locked queue(mWorkQueue);
        while (!items->empty()) {
            queue->mQueue.push_back(std::move(items->front()));
            queue->push_back(std::move(items->front()));
            items->pop_front();
        }
        queue->mCondition.broadcast();
@@ -79,10 +106,12 @@ c2_status_t SimpleC2Component::flush_sm(
    }
    {
        Mutexed<WorkQueue>::Locked queue(mWorkQueue);
        ++queue->mGeneration;
        while (!queue->mQueue.empty()) {
            flushedWork->push_back(std::move(queue->mQueue.front()));
            queue->mQueue.pop_front();
        queue->incGeneration();
        while (!queue->empty()) {
            std::unique_ptr<C2Work> work = queue->pop_front();
            if (work) {
                flushedWork->push_back(std::move(work));
            }
        }
    }
    {
@@ -96,8 +125,10 @@ c2_status_t SimpleC2Component::flush_sm(
    return onFlush_sm();
}

c2_status_t SimpleC2Component::drain_nb(drain_mode_t drainThrough) {
    (void) drainThrough;
c2_status_t SimpleC2Component::drain_nb(drain_mode_t drainMode) {
    if (drainMode == DRAIN_CHAIN) {
        return C2_OMITTED;
    }
    {
        Mutexed<ExecState>::Locked state(mExecState);
        if (state->mState != RUNNING) {
@@ -106,14 +137,11 @@ c2_status_t SimpleC2Component::drain_nb(drain_mode_t drainThrough) {
    }
    {
        Mutexed<WorkQueue>::Locked queue(mWorkQueue);
        if (!queue->mQueue.empty()) {
            const std::unique_ptr<C2Work> &work = queue->mQueue.back();
            work->input.flags = (C2BufferPack::flags_t)(work->input.flags | C2BufferPack::FLAG_END_OF_STREAM);
            return C2_OK;
        }
        queue->markDrain(drainMode);
        queue->mCondition.broadcast();
    }

    return onDrain_nb();
    return C2_OK;
}

c2_status_t SimpleC2Component::start() {
@@ -161,7 +189,7 @@ c2_status_t SimpleC2Component::stop() {
    }
    {
        Mutexed<WorkQueue>::Locked queue(mWorkQueue);
        queue->mQueue.clear();
        queue->clear();
    }
    {
        Mutexed<PendingWork>::Locked pending(mPendingWork);
@@ -181,7 +209,7 @@ c2_status_t SimpleC2Component::reset() {
    }
    {
        Mutexed<WorkQueue>::Locked queue(mWorkQueue);
        queue->mQueue.clear();
        queue->clear();
    }
    {
        Mutexed<PendingWork>::Locked pending(mPendingWork);
@@ -192,11 +220,13 @@ c2_status_t SimpleC2Component::reset() {
}

c2_status_t SimpleC2Component::release() {
    std::thread releasing;
    {
        Mutexed<ExecState>::Locked state(mExecState);
        mExitRequested = true;
        state->mThread.join();
        releasing = std::move(state->mThread);
    }
    mExitRequested = true;
    releasing.join();
    onRelease();
    return C2_OK;
}
@@ -221,6 +251,7 @@ void SimpleC2Component::finish(
    {
        Mutexed<PendingWork>::Locked pending(mPendingWork);
        if (pending->count(frameIndex) == 0) {
            ALOGW("unknown frame index: %" PRIu64, frameIndex);
            return;
        }
        work = std::move(pending->at(frameIndex));
@@ -230,34 +261,56 @@ void SimpleC2Component::finish(
        fillWork(work);
        Mutexed<ExecState>::Locked state(mExecState);
        state->mListener->onWorkDone_nb(shared_from_this(), vec(work));
        ALOGV("returning pending work");
    }
}

void SimpleC2Component::processQueue() {
    std::unique_ptr<C2Work> work;
    uint64_t generation;
    int32_t drainMode;
    {
        Mutexed<WorkQueue>::Locked queue(mWorkQueue);
        nsecs_t deadline = systemTime() + ms2ns(250);
        while (queue->mQueue.empty()) {
            status_t err = queue.waitForConditionRelative(
                    queue->mCondition, std::max(deadline - systemTime(), (nsecs_t)0));
        while (queue->empty()) {
            nsecs_t now = systemTime();
            if (now >= deadline) {
                return;
            }
            status_t err = queue.waitForConditionRelative(queue->mCondition, deadline - now);
            if (err == TIMED_OUT) {
                return;
            }
        }

        generation = queue->mGeneration;
        work = std::move(queue->mQueue.front());
        queue->mQueue.pop_front();
    }
    if (!work) {
        return;
        generation = queue->generation();
        drainMode = queue->drainMode();
        work = queue->pop_front();
    }

    // TODO: grab pool ID from intf
    if (!mOutputBlockPool) {
        c2_status_t err = GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, shared_from_this(), &mOutputBlockPool);
        c2_status_t err = [this] {
            // TODO: don't use query_vb
            C2StreamFormatConfig::output outputFormat(0u);
            c2_status_t err = intf()->query_vb(
                    { &outputFormat },
                    {},
                    C2_DONT_BLOCK,
                    nullptr);
            if (err != C2_OK) {
                return err;
            }
            err = GetCodec2BlockPool(
                    (outputFormat.value == C2FormatVideo)
                    ? C2BlockPool::BASIC_GRAPHIC
                    : C2BlockPool::BASIC_LINEAR,
                    shared_from_this(),
                    &mOutputBlockPool);
            if (err != C2_OK) {
                return err;
            }
            return C2_OK;
        }();
        if (err != C2_OK) {
            Mutexed<ExecState>::Locked state(mExecState);
            state->mListener->onError_nb(shared_from_this(), err);
@@ -265,10 +318,20 @@ void SimpleC2Component::processQueue() {
        }
    }

    bool done = process(work, mOutputBlockPool);
    if (!work) {
        c2_status_t err = drain(drainMode, mOutputBlockPool);
        if (err != C2_OK) {
            Mutexed<ExecState>::Locked state(mExecState);
            state->mListener->onError_nb(shared_from_this(), err);
        }
        return;
    }

    process(work, mOutputBlockPool);
    {
        Mutexed<WorkQueue>::Locked queue(mWorkQueue);
        if (queue->mGeneration != generation) {
        if (queue->generation() != generation) {
            ALOGW("work form old generation: was %" PRIu64 " now %" PRIu64, queue->generation(), generation);
            work->result = C2_NOT_FOUND;
            queue.unlock();
            {
@@ -279,10 +342,12 @@ void SimpleC2Component::processQueue() {
            return;
        }
    }
    if (done) {
    if (work->worklets_processed != 0u) {
        Mutexed<ExecState>::Locked state(mExecState);
        ALOGV("returning this work");
        state->mListener->onWorkDone_nb(shared_from_this(), vec(work));
    } else {
        ALOGV("queue pending work");
        std::unique_ptr<C2Work> unexpected;
        {
            Mutexed<PendingWork>::Locked pending(mPendingWork);
@@ -301,4 +366,45 @@ void SimpleC2Component::processQueue() {
    }
}

namespace {

class GraphicBuffer : public C2Buffer {
public:
    GraphicBuffer(
            const std::shared_ptr<C2GraphicBlock> &block,
            const C2Rect &crop)
        : C2Buffer({ block->share(crop, ::android::C2Fence()) }) {}
};


class LinearBuffer : public C2Buffer {
public:
    LinearBuffer(
            const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size)
        : C2Buffer({ block->share(offset, size, ::android::C2Fence()) }) {}
};

}  // namespace

std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer(
        const std::shared_ptr<C2LinearBlock> &block) {
    return createLinearBuffer(block, block->offset(), block->size());
}

std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer(
        const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size) {
    return std::make_shared<LinearBuffer>(block, offset, size);
}

std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer(
        const std::shared_ptr<C2GraphicBlock> &block) {
    return createGraphicBuffer(block, C2Rect(0, 0, block->width(), block->height()));
}

std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer(
        const std::shared_ptr<C2GraphicBlock> &block,
        const C2Rect &crop) {
    return std::make_shared<GraphicBuffer>(block, crop);
}

} // namespace android
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "SimpleC2Interface"
#include <utils/Log.h>

#include <SimpleC2Interface.h>

namespace android {

c2_status_t SimpleC2Interface::query_vb(
        const std::vector<C2Param* const> &stackParams,
        const std::vector<C2Param::Index> &heapParamIndices,
        c2_blocking_t mayBlock,
        std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
    (void)mayBlock;

    for (C2Param* const param : stackParams) {
        if (param->coreIndex() != C2StreamFormatConfig::CORE_INDEX
                || !param->forStream()
                || param->stream() != 0u) {
            param->invalidate();
            continue;
        }
        if (param->forInput()) {
            param->updateFrom(mInputFormat);
        } else {
            param->updateFrom(mOutputFormat);
        }
    }
    if (heapParams) {
        heapParams->clear();
        for (const auto &index : heapParamIndices) {
            if (index.coreIndex() != C2StreamFormatConfig::CORE_INDEX
                    || !index.forStream()
                    || index.stream() != 0u) {
                heapParams->push_back(nullptr);
            }
            if (index.forInput()) {
                heapParams->push_back(C2Param::Copy(mInputFormat));
            } else {
                heapParams->push_back(C2Param::Copy(mOutputFormat));
            }
        }
    }

    return C2_OK;
}

} // namespace android
+53 −13
Original line number Diff line number Diff line
@@ -84,23 +84,28 @@ protected:
    virtual c2_status_t onFlush_sm() = 0;

    /**
     * Drain the component.
     * Process the given work and finish pending work using finish().
     *
     * \param[in,out]   work    the work to process
     * \param[in]       pool    the pool to use for allocating output blocks.
     */
    virtual c2_status_t onDrain_nb() = 0;
    virtual void process(
            const std::unique_ptr<C2Work> &work,
            const std::shared_ptr<C2BlockPool> &pool) = 0;

    /**
     * Process the given work and finish pending work using finish().
     * Drain the component and finish pending work using finish().
     *
     * \param[in,out]   work    the work to process
     * \param[in]   drainMode   mode of drain.
     * \param[in]   pool        the pool to use for allocating output blocks.
     *
     * \retval true             |work| is done and ready for return to client
     * \retval false            more data is needed for the |work| to be done;
     *                          mark |work| as pending.
     * \retval C2_OK            The component has drained all pending output
     *                          work.
     * \retval C2_OMITTED       Unsupported mode (e.g. DRAIN_CHAIN)
     */
    virtual bool process(
            const std::unique_ptr<C2Work> &work,
            std::shared_ptr<C2BlockPool> pool) = 0;
    virtual c2_status_t drain(
            uint32_t drainMode,
            const std::shared_ptr<C2BlockPool> &pool) = 0;

    // for derived classes
    /**
@@ -116,6 +121,21 @@ protected:
     */
    void finish(uint64_t frameIndex, std::function<void(const std::unique_ptr<C2Work> &)> fillWork);

    std::shared_ptr<C2Buffer> createLinearBuffer(
            const std::shared_ptr<C2LinearBlock> &block);

    std::shared_ptr<C2Buffer> createLinearBuffer(
            const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size);

    std::shared_ptr<C2Buffer> createGraphicBuffer(
            const std::shared_ptr<C2GraphicBlock> &block);

    std::shared_ptr<C2Buffer> createGraphicBuffer(
            const std::shared_ptr<C2GraphicBlock> &block,
            const C2Rect &crop);

    static constexpr uint32_t NO_DRAIN = ~0u;

private:
    const std::shared_ptr<C2ComponentInterface> mIntf;
    std::atomic_bool mExitRequested;
@@ -135,10 +155,30 @@ private:
    };
    Mutexed<ExecState> mExecState;

    struct WorkQueue {
    class WorkQueue {
    public:
        inline WorkQueue() : mGeneration(0ul) {}

        inline uint64_t generation() const { return mGeneration; }
        inline void incGeneration() { ++mGeneration; }

        std::unique_ptr<C2Work> pop_front();
        void push_back(std::unique_ptr<C2Work> work);
        bool empty() const;
        uint32_t drainMode() const;
        void markDrain(uint32_t drainMode);
        void clear();

        Condition mCondition;
        std::list<std::unique_ptr<C2Work>> mQueue;

    private:
        struct Entry {
            std::unique_ptr<C2Work> work;
            uint32_t drainMode;
        };

        uint64_t mGeneration;
        std::list<Entry> mQueue;
    };
    Mutexed<WorkQueue> mWorkQueue;

+98 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SIMPLE_C2_INTERFACE_H_
#define SIMPLE_C2_INTERFACE_H_

#include <C2Component.h>

namespace android {

class SimpleC2Interface : public C2ComponentInterface {
public:
    class Builder {
    public:
        inline Builder(
                const char *name,
                c2_node_id_t id)
            : mIntf(new SimpleC2Interface(name, id)) {}

        inline Builder(
                const char *name,
                c2_node_id_t id,
                std::function<void(::android::SimpleC2Interface*)> deleter)
            : mIntf(new SimpleC2Interface(name, id), deleter) {}

        inline Builder &inputFormat(C2FormatKind input) {
            mIntf->mInputFormat.value = input;
            return *this;
        }

        inline Builder &outputFormat(C2FormatKind output) {
            mIntf->mOutputFormat.value = output;
            return *this;
        }

        inline std::shared_ptr<SimpleC2Interface> build() {
            return mIntf;
        }
    private:
        std::shared_ptr<SimpleC2Interface> mIntf;
    };

    virtual ~SimpleC2Interface() = default;

    // From C2ComponentInterface
    inline C2String getName() const override { return mName; }
    inline c2_node_id_t getId() const override { return mId; }
    c2_status_t query_vb(
            const std::vector<C2Param* const> &stackParams,
            const std::vector<C2Param::Index> &heapParamIndices,
            c2_blocking_t mayBlock,
            std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
    inline c2_status_t config_vb(
            const std::vector<C2Param* const> &,
            c2_blocking_t,
            std::vector<std::unique_ptr<C2SettingResult>>* const) override {
        return C2_OMITTED;
    }
    inline c2_status_t createTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
    inline c2_status_t releaseTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
    inline c2_status_t querySupportedParams_nb(
            std::vector<std::shared_ptr<C2ParamDescriptor>> * const) const override {
        return C2_OMITTED;
    }
    c2_status_t querySupportedValues_vb(
            std::vector<C2FieldSupportedValuesQuery> &,
            c2_blocking_t) const override {
        return C2_OMITTED;
    }

private:
    inline SimpleC2Interface(const char *name, c2_node_id_t id)
        : mName(name), mId(id), mInputFormat(0u), mOutputFormat(0u) {}

    const C2String mName;
    const c2_node_id_t mId;
    C2StreamFormatConfig::input mInputFormat;
    C2StreamFormatConfig::output mOutputFormat;

    SimpleC2Interface() = delete;
};

}  // namespace android

#endif  // SIMPLE_C2_INTERFACE_H_
Loading