diff options
Diffstat (limited to 'media/codecs/base/SimpleC2Component.cpp')
| -rw-r--r-- | media/codecs/base/SimpleC2Component.cpp | 569 |
1 files changed, 0 insertions, 569 deletions
diff --git a/media/codecs/base/SimpleC2Component.cpp b/media/codecs/base/SimpleC2Component.cpp deleted file mode 100644 index 50b4d20..0000000 --- a/media/codecs/base/SimpleC2Component.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/* - * 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 "SimpleC2Component" -#include <log/log.h> - -#include <cutils/properties.h> -#include <media/stagefright/foundation/AMessage.h> - -#include <inttypes.h> - -#include <C2Config.h> -#include <C2Debug.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::WorkHandler::WorkHandler() : mRunning(false) {} - -void SimpleC2Component::WorkHandler::setComponent( - const std::shared_ptr<SimpleC2Component> &thiz) { - mThiz = thiz; -} - -static void Reply(const sp<AMessage> &msg, int32_t *err = nullptr) { - sp<AReplyToken> replyId; - CHECK(msg->senderAwaitsResponse(&replyId)); - sp<AMessage> reply = new AMessage; - if (err) { - reply->setInt32("err", *err); - } - reply->postReply(replyId); -} - -void SimpleC2Component::WorkHandler::onMessageReceived(const sp<AMessage> &msg) { - std::shared_ptr<SimpleC2Component> thiz = mThiz.lock(); - if (!thiz) { - ALOGD("component not yet set; msg = %s", msg->debugString().c_str()); - sp<AReplyToken> replyId; - if (msg->senderAwaitsResponse(&replyId)) { - sp<AMessage> reply = new AMessage; - reply->setInt32("err", C2_CORRUPTED); - reply->postReply(replyId); - } - return; - } - - switch (msg->what()) { - case kWhatProcess: { - if (mRunning) { - if (thiz->processQueue()) { - (new AMessage(kWhatProcess, this))->post(); - } - } else { - ALOGV("Ignore process message as we're not running"); - } - break; - } - case kWhatInit: { - int32_t err = thiz->onInit(); - Reply(msg, &err); - [[fallthrough]]; - } - case kWhatStart: { - mRunning = true; - break; - } - case kWhatStop: { - int32_t err = thiz->onStop(); - Reply(msg, &err); - break; - } - case kWhatReset: { - thiz->onReset(); - mRunning = false; - Reply(msg); - break; - } - case kWhatRelease: { - thiz->onRelease(); - mRunning = false; - Reply(msg); - break; - } - default: { - ALOGD("Unrecognized msg: %d", msg->what()); - break; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// - -namespace { - -struct DummyReadView : public C2ReadView { - DummyReadView() : C2ReadView(C2_NO_INIT) {} -}; - -} // namespace - -SimpleC2Component::SimpleC2Component( - const std::shared_ptr<C2ComponentInterface> &intf) - : mDummyReadView(DummyReadView()), - mIntf(intf), - mLooper(new ALooper), - mHandler(new WorkHandler) { - mLooper->setName(intf->getName().c_str()); - (void)mLooper->registerHandler(mHandler); - mLooper->start(false, false, ANDROID_PRIORITY_VIDEO); -} - -SimpleC2Component::~SimpleC2Component() { - mLooper->unregisterHandler(mHandler->id()); - (void)mLooper->stop(); -} - -c2_status_t SimpleC2Component::setListener_vb( - const std::shared_ptr<C2Component::Listener> &listener, c2_blocking_t mayBlock) { - mHandler->setComponent(shared_from_this()); - - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState == RUNNING) { - if (listener) { - return C2_BAD_STATE; - } else if (!mayBlock) { - return C2_BLOCKING; - } - } - state->mListener = listener; - // TODO: wait for listener change to have taken place before returning - // (e.g. if there is an ongoing listener callback) - return C2_OK; -} - -c2_status_t SimpleC2Component::queue_nb(std::list<std::unique_ptr<C2Work>> * const items) { - { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState != RUNNING) { - return C2_BAD_STATE; - } - } - bool queueWasEmpty = false; - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queueWasEmpty = queue->empty(); - while (!items->empty()) { - queue->push_back(std::move(items->front())); - items->pop_front(); - } - } - if (queueWasEmpty) { - (new AMessage(WorkHandler::kWhatProcess, mHandler))->post(); - } - return C2_OK; -} - -c2_status_t SimpleC2Component::announce_nb(const std::vector<C2WorkOutline> &items) { - (void)items; - return C2_OMITTED; -} - -c2_status_t SimpleC2Component::flush_sm( - flush_mode_t flushMode, std::list<std::unique_ptr<C2Work>>* const flushedWork) { - (void)flushMode; - { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState != RUNNING) { - return C2_BAD_STATE; - } - } - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queue->incGeneration(); - // TODO: queue->splicedBy(flushedWork, flushedWork->end()); - while (!queue->empty()) { - std::unique_ptr<C2Work> work = queue->pop_front(); - if (work) { - flushedWork->push_back(std::move(work)); - } - } - } - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - while (!pending->empty()) { - flushedWork->push_back(std::move(pending->begin()->second)); - pending->erase(pending->begin()); - } - } - - return C2_OK; -} - -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) { - return C2_BAD_STATE; - } - } - bool queueWasEmpty = false; - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queueWasEmpty = queue->empty(); - queue->markDrain(drainMode); - } - if (queueWasEmpty) { - (new AMessage(WorkHandler::kWhatProcess, mHandler))->post(); - } - - return C2_OK; -} - -c2_status_t SimpleC2Component::start() { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState == RUNNING) { - return C2_BAD_STATE; - } - bool needsInit = (state->mState == UNINITIALIZED); - state.unlock(); - if (needsInit) { - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatInit, mHandler))->postAndAwaitResponse(&reply); - int32_t err; - CHECK(reply->findInt32("err", &err)); - if (err != C2_OK) { - return (c2_status_t)err; - } - } else { - (new AMessage(WorkHandler::kWhatStart, mHandler))->post(); - } - state.lock(); - state->mState = RUNNING; - return C2_OK; -} - -c2_status_t SimpleC2Component::stop() { - ALOGV("stop"); - { - Mutexed<ExecState>::Locked state(mExecState); - if (state->mState != RUNNING) { - return C2_BAD_STATE; - } - state->mState = STOPPED; - } - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queue->clear(); - } - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - pending->clear(); - } - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatStop, mHandler))->postAndAwaitResponse(&reply); - int32_t err; - CHECK(reply->findInt32("err", &err)); - if (err != C2_OK) { - return (c2_status_t)err; - } - return C2_OK; -} - -c2_status_t SimpleC2Component::reset() { - ALOGV("reset"); - { - Mutexed<ExecState>::Locked state(mExecState); - state->mState = UNINITIALIZED; - } - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - queue->clear(); - } - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - pending->clear(); - } - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatReset, mHandler))->postAndAwaitResponse(&reply); - return C2_OK; -} - -c2_status_t SimpleC2Component::release() { - ALOGV("release"); - sp<AMessage> reply; - (new AMessage(WorkHandler::kWhatRelease, mHandler))->postAndAwaitResponse(&reply); - return C2_OK; -} - -std::shared_ptr<C2ComponentInterface> SimpleC2Component::intf() { - return mIntf; -} - -namespace { - -std::list<std::unique_ptr<C2Work>> vec(std::unique_ptr<C2Work> &work) { - std::list<std::unique_ptr<C2Work>> ret; - ret.push_back(std::move(work)); - return ret; -} - -} // namespace - -void SimpleC2Component::finish( - uint64_t frameIndex, std::function<void(const std::unique_ptr<C2Work> &)> fillWork) { - std::unique_ptr<C2Work> work; - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - if (pending->count(frameIndex) == 0) { - ALOGW("unknown frame index: %" PRIu64, frameIndex); - return; - } - work = std::move(pending->at(frameIndex)); - pending->erase(frameIndex); - } - if (work) { - fillWork(work); - std::shared_ptr<C2Component::Listener> listener = mExecState.lock()->mListener; - listener->onWorkDone_nb(shared_from_this(), vec(work)); - ALOGV("returning pending work"); - } -} - -void SimpleC2Component::cloneAndSend( - uint64_t frameIndex, - const std::unique_ptr<C2Work> ¤tWork, - std::function<void(const std::unique_ptr<C2Work> &)> fillWork) { - std::unique_ptr<C2Work> work(new C2Work); - if (currentWork->input.ordinal.frameIndex == frameIndex) { - work->input.flags = currentWork->input.flags; - work->input.ordinal = currentWork->input.ordinal; - } else { - Mutexed<PendingWork>::Locked pending(mPendingWork); - if (pending->count(frameIndex) == 0) { - ALOGW("unknown frame index: %" PRIu64, frameIndex); - return; - } - work->input.flags = pending->at(frameIndex)->input.flags; - work->input.ordinal = pending->at(frameIndex)->input.ordinal; - } - work->worklets.emplace_back(new C2Worklet); - if (work) { - fillWork(work); - std::shared_ptr<C2Component::Listener> listener = mExecState.lock()->mListener; - listener->onWorkDone_nb(shared_from_this(), vec(work)); - ALOGV("cloned and sending work"); - } -} - -bool SimpleC2Component::processQueue() { - std::unique_ptr<C2Work> work; - uint64_t generation; - int32_t drainMode; - bool isFlushPending = false; - bool hasQueuedWork = false; - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - if (queue->empty()) { - return false; - } - - generation = queue->generation(); - drainMode = queue->drainMode(); - isFlushPending = queue->popPendingFlush(); - work = queue->pop_front(); - hasQueuedWork = !queue->empty(); - } - if (isFlushPending) { - ALOGV("processing pending flush"); - c2_status_t err = onFlush_sm(); - if (err != C2_OK) { - ALOGD("flush err: %d", err); - // TODO: error - } - } - - if (!mOutputBlockPool) { - c2_status_t err = [this] { - // TODO: don't use query_vb - C2StreamFormatConfig::output outputFormat(0u); - std::vector<std::unique_ptr<C2Param>> params; - c2_status_t err = intf()->query_vb( - { &outputFormat }, - { C2PortBlockPoolsTuning::output::PARAM_TYPE }, - C2_DONT_BLOCK, - ¶ms); - if (err != C2_OK && err != C2_BAD_INDEX) { - ALOGD("query err = %d", err); - return err; - } - C2BlockPool::local_id_t poolId = - outputFormat.value == C2FormatVideo - ? C2BlockPool::BASIC_GRAPHIC - : C2BlockPool::BASIC_LINEAR; - if (params.size()) { - C2PortBlockPoolsTuning::output *outputPools = - C2PortBlockPoolsTuning::output::From(params[0].get()); - if (outputPools && outputPools->flexCount() >= 1) { - poolId = outputPools->m.values[0]; - } - } - - err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool); - ALOGD("Using output block pool with poolID %llu => got %llu - %d", - (unsigned long long)poolId, - (unsigned long long)( - mOutputBlockPool ? mOutputBlockPool->getLocalId() : 111000111), - err); - return err; - }(); - if (err != C2_OK) { - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onError_nb(shared_from_this(), err); - return hasQueuedWork; - } - } - - if (!work) { - c2_status_t err = drain(drainMode, mOutputBlockPool); - if (err != C2_OK) { - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onError_nb(shared_from_this(), err); - } - return hasQueuedWork; - } - - { - std::vector<C2Param *> updates; - for (const std::unique_ptr<C2Param> ¶m: work->input.configUpdate) { - if (param) { - updates.emplace_back(param.get()); - } - } - if (!updates.empty()) { - std::vector<std::unique_ptr<C2SettingResult>> failures; - c2_status_t err = intf()->config_vb(updates, C2_MAY_BLOCK, &failures); - ALOGD("applied %zu configUpdates => %s (%d)", updates.size(), asString(err), err); - } - } - - ALOGV("start processing frame #%" PRIu64, work->input.ordinal.frameIndex.peeku()); - // If input buffer list is not empty, it means we have some input to process on. - // However, input could be a null buffer. In such case, clear the buffer list - // before making call to process(). - if (!work->input.buffers.empty() && !work->input.buffers[0]) { - ALOGD("Encountered null input buffer. Clearing the input buffer"); - work->input.buffers.clear(); - } - process(work, mOutputBlockPool); - ALOGV("processed frame #%" PRIu64, work->input.ordinal.frameIndex.peeku()); - { - Mutexed<WorkQueue>::Locked queue(mWorkQueue); - if (queue->generation() != generation) { - ALOGD("work form old generation: was %" PRIu64 " now %" PRIu64, - queue->generation(), generation); - work->result = C2_NOT_FOUND; - queue.unlock(); - { - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onWorkDone_nb(shared_from_this(), vec(work)); - } - queue.lock(); - return hasQueuedWork; - } - } - if (work->workletsProcessed != 0u) { - Mutexed<ExecState>::Locked state(mExecState); - ALOGV("returning this work"); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onWorkDone_nb(shared_from_this(), vec(work)); - } else { - ALOGV("queue pending work"); - work->input.buffers.clear(); - std::unique_ptr<C2Work> unexpected; - { - Mutexed<PendingWork>::Locked pending(mPendingWork); - uint64_t frameIndex = work->input.ordinal.frameIndex.peeku(); - if (pending->count(frameIndex) != 0) { - unexpected = std::move(pending->at(frameIndex)); - pending->erase(frameIndex); - } - (void)pending->insert({ frameIndex, std::move(work) }); - } - if (unexpected) { - ALOGD("unexpected pending work"); - unexpected->result = C2_CORRUPTED; - Mutexed<ExecState>::Locked state(mExecState); - std::shared_ptr<C2Component::Listener> listener = state->mListener; - state.unlock(); - listener->onWorkDone_nb(shared_from_this(), vec(unexpected)); - } - } - return hasQueuedWork; -} - -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 C2Buffer::CreateLinearBuffer(block->share(offset, size, ::C2Fence())); -} - -std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer( - const std::shared_ptr<C2GraphicBlock> &block) { - return createGraphicBuffer(block, C2Rect(block->width(), block->height())); -} - -std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer( - const std::shared_ptr<C2GraphicBlock> &block, const C2Rect &crop) { - return C2Buffer::CreateGraphicBuffer(block->share(crop, ::C2Fence())); -} - -} // namespace android |
