Loading media/libstagefright/codec2/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,10 @@ cc_library_shared { "optional", ], srcs: ["SimpleC2Component.cpp"], srcs: [ "SimpleC2Component.cpp", "SimpleC2Interface.cpp", ], include_dirs: [ ], Loading media/libstagefright/codec2/SimpleC2Component.cpp +138 −32 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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(); Loading @@ -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)); } } } { Loading @@ -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) { Loading @@ -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() { Loading Loading @@ -161,7 +189,7 @@ c2_status_t SimpleC2Component::stop() { } { Mutexed<WorkQueue>::Locked queue(mWorkQueue); queue->mQueue.clear(); queue->clear(); } { Mutexed<PendingWork>::Locked pending(mPendingWork); Loading @@ -181,7 +209,7 @@ c2_status_t SimpleC2Component::reset() { } { Mutexed<WorkQueue>::Locked queue(mWorkQueue); queue->mQueue.clear(); queue->clear(); } { Mutexed<PendingWork>::Locked pending(mPendingWork); Loading @@ -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; } Loading @@ -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)); Loading @@ -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); Loading @@ -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(); { Loading @@ -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); Loading @@ -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 media/libstagefright/codec2/SimpleC2Interface.cpp 0 → 100644 +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 media/libstagefright/codec2/include/SimpleC2Component.h +53 −13 Original line number Diff line number Diff line Loading @@ -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 /** Loading @@ -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; Loading @@ -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; Loading media/libstagefright/codec2/include/SimpleC2Interface.h 0 → 100644 +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
media/libstagefright/codec2/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,10 @@ cc_library_shared { "optional", ], srcs: ["SimpleC2Component.cpp"], srcs: [ "SimpleC2Component.cpp", "SimpleC2Interface.cpp", ], include_dirs: [ ], Loading
media/libstagefright/codec2/SimpleC2Component.cpp +138 −32 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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(); Loading @@ -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)); } } } { Loading @@ -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) { Loading @@ -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() { Loading Loading @@ -161,7 +189,7 @@ c2_status_t SimpleC2Component::stop() { } { Mutexed<WorkQueue>::Locked queue(mWorkQueue); queue->mQueue.clear(); queue->clear(); } { Mutexed<PendingWork>::Locked pending(mPendingWork); Loading @@ -181,7 +209,7 @@ c2_status_t SimpleC2Component::reset() { } { Mutexed<WorkQueue>::Locked queue(mWorkQueue); queue->mQueue.clear(); queue->clear(); } { Mutexed<PendingWork>::Locked pending(mPendingWork); Loading @@ -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; } Loading @@ -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)); Loading @@ -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); Loading @@ -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(); { Loading @@ -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); Loading @@ -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
media/libstagefright/codec2/SimpleC2Interface.cpp 0 → 100644 +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
media/libstagefright/codec2/include/SimpleC2Component.h +53 −13 Original line number Diff line number Diff line Loading @@ -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 /** Loading @@ -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; Loading @@ -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; Loading
media/libstagefright/codec2/include/SimpleC2Interface.h 0 → 100644 +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_