基于Android12的Codec2.0的解码插件,实现多线程并发解码
主类实现OutFrameThread接口,拆分原来的process,送输入和取输出进行异步运作。
diff --git a/component/base/Android.bp b/component/base/Android.bp
index 1d2103c..eb7684a 100644
--- a/component/base/Android.bp
+++ b/component/base/Android.bp
@@ -54,6 +54,7 @@
srcs: [
"C2RKComponent.cpp",
"C2RKInterface.cpp",
+ "OutFrameThread.cpp",
],
include_dirs: [
diff --git a/component/base/C2RKComponent.cpp b/component/base/C2RKComponent.cpp
index 1a8ecc5..be8e02c 100755
--- a/component/base/C2RKComponent.cpp
+++ b/component/base/C2RKComponent.cpp
@@ -196,9 +196,35 @@
} // namespace
+void C2RKComponent::run() {
+ if(isEncoder)
+ return;
+ while (mThreadEnabled.load()) {
+ c2_trace("run()");
+ Mutexed<WorkQueue>::Locked queue(mWorkQueue);
+ if (!queue->pending().empty()) {
+ queue.unlock();
+ outputPart(mOutputBlockPool);
+ }
+ }
+ c2_info_f("exit");
+}
+
+c2_status_t C2RKComponent::stopOutFrameThread() {
+ c2_info_f("C2RKComponent::stopOutFrameThread()");
+ c2_status_t result = C2_OK;
+ // clear flag that tells thread to loop
+ if (mThreadEnabled.exchange(false)) {
+ c2_info_f("mOutFrameThread.stop");
+ result = mOutFrameThread.stop();
+ }
+ return result;
+}
+
C2RKComponent::C2RKComponent(
const std::shared_ptr<C2ComponentInterface> &intf)
- : mDummyReadView(DummyReadView()),
+ : mOutFrameThread("OutFrameThread"),
+ mDummyReadView(DummyReadView()),
mIntf(intf),
mLooper(new ALooper),
mHandler(new WorkHandler) {
@@ -277,7 +303,11 @@
c2_status_t C2RKComponent::flush_sm(
flush_mode_t flushMode, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
FunctionIn();
-
+ // When ready to flush, stop the thread fetching data
+ if (mThreadEnabled.exchange(false) && !isEncoder) {
+ c2_info_f("mOutFrameThread.stop");
+ mOutFrameThread.stop();
+ }
(void)flushMode;
{
Mutexed<ExecState>::Locked state(mExecState);
@@ -335,7 +365,7 @@
c2_status_t C2RKComponent::start() {
FunctionIn();
-
+ int32_t err;
Mutexed<ExecState>::Locked state(mExecState);
if (state->mState == RUNNING) {
return C2_BAD_STATE;
@@ -355,7 +385,15 @@
}
state.lock();
state->mState = RUNNING;
+ if (!isEncoder) {
+ mThreadEnabled.store(true);
+ err = mOutFrameThread.start(this);
+ if (err != C2_OK) {
+ c2_err("C2RKComponent mOutFrameThread err: %d", err);
+ return (c2_status_t)err;
+ }
+ }
FunctionOut();
return C2_OK;
@@ -363,6 +401,8 @@
c2_status_t C2RKComponent::stop() {
c2_info("stop in");
+ if(!isEncoder)
+ stopOutFrameThread();
{
Mutexed<ExecState>::Locked state(mExecState);
if (state->mState != RUNNING) {
@@ -403,6 +443,7 @@
c2_status_t C2RKComponent::release() {
c2_info("release in");
+ stopOutFrameThread();
sp<AMessage> reply;
(new AMessage(WorkHandler::kWhatRelease, mHandler))->postAndAwaitResponse(&reply);
return C2_OK;
@@ -427,11 +468,7 @@
std::function<void(const std::unique_ptr<C2Work> &)> fillWork,
bool delayOutput) {
std::unique_ptr<C2Work> work;
-
- if (delayOutput) {
- mReadyWork.push_back({ frameIndex, fillWork });
- return;
- }
+ (void) delayOutput;
if (frameIndex == I2O4INDEX) {
c2_trace("C2RKComponent::finish i2o4");
@@ -443,7 +480,6 @@
listener->onWorkDone_nb(shared_from_this(), vec(outputWork));
return;
}
-
{
Mutexed<WorkQueue>::Locked queue(mWorkQueue);
if (queue->pending().count(frameIndex) == 0) {
@@ -461,6 +497,14 @@
}
}
+void C2RKComponent::finishEosWork(uint64_t frameIndex,std::unique_ptr<C2Work> ¤tWork) {
+ if (currentWork) {
+ std::shared_ptr<C2Component::Listener> listener = mExecState.lock()->mListener;
+ listener->onWorkDone_nb(shared_from_this(), vec(currentWork));
+ c2_trace("finishEosWork %" PRIu64, frameIndex);
+ }
+}
+
void C2RKComponent::cloneAndSend(
uint64_t frameIndex,
const std::unique_ptr<C2Work> ¤tWork,
@@ -481,15 +525,16 @@
work->worklets.emplace_back(new C2Worklet);
if (work) {
fillWork(work);
+ c2_trace("cloned and sending work #%" PRIu64,
+ work->input.ordinal.frameIndex.peeku());
std::shared_ptr<C2Component::Listener> listener = mExecState.lock()->mListener;
listener->onWorkDone_nb(shared_from_this(), vec(work));
- c2_trace("cloned and sending work");
}
}
bool C2RKComponent::processQueue() {
std::unique_ptr<C2Work> work;
- uint64_t generation;
+
int32_t drainMode;
bool isFlushPending = false;
bool hasQueuedWork = false;
@@ -508,6 +553,12 @@
if (isFlushPending) {
c2_trace("processing pending flush");
c2_status_t err = onFlush_sm();
+ // After the buffer is freed, the thread needs to be restarted to
+ // refetch the output data and then queue the input data again
+ if (!isEncoder) {
+ mThreadEnabled.store(true);
+ err = mOutFrameThread.start(this);
+ }
if (err != C2_OK) {
c2_err("flush err: %d", err);
// TODO: error
@@ -600,6 +651,10 @@
work->input.buffers.clear();
}
}
+ if (!isEncoder) {
+ processInput(work, mOutputBlockPool);
+ }
+ else{
process(work, mOutputBlockPool);
c2_trace("processed frame #%" PRIu64, work->input.ordinal.frameIndex.peeku());
Mutexed<WorkQueue>::Locked queue(mWorkQueue);
@@ -651,7 +706,24 @@
listener->onWorkDone_nb(shared_from_this(), vec(unexpected));
}
}
- return hasQueuedWork;
+ }
+ return true;
+}
+
+void C2RKComponent::processInput(
+ std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) {
+ uint64_t frameIndex = work->input.ordinal.frameIndex.peekull();
+ std::unique_ptr<C2Work> currentWork = std::move(work);
+
+ inputPart(currentWork, pool);
+ if(currentWork->result != C2_OK){
+ c2_trace("Work->result NOK");
+ return;
+ }
+ Mutexed<WorkQueue>::Locked queue(mWorkQueue);
+ (void)queue->pending().insert({ frameIndex, std::move(currentWork) });
+ queue.unlock();
}
std::shared_ptr<C2Buffer> C2RKComponent::createLinearBuffer(
diff --git a/component/base/OutFrameThread.cpp b/component/base/OutFrameThread.cpp
new file mode 100755
index 0000000..b33f497
--- /dev/null
+++ b/component/base/OutFrameThread.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 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_TAG "OutFrameThread"
+#define LOG_NDEBUG 0
+#include <sys/resource.h>
+#include <utils/Log.h>
+
+#include <pthread.h>
+
+//#include <aaudio/AAudio.h>
+//#include <utility/AAudioUtilities.h>
+
+#include "OutFrameThread.h"
+
+
+std::atomic<uint32_t> OutFrameThread::mNextThreadIndex{1};
+
+OutFrameThread::OutFrameThread(const char *prefix) {
+ setup(prefix);
+}
+
+OutFrameThread::OutFrameThread() {
+ setup("OutFrame");
+}
+
+OutFrameThread::~OutFrameThread() {
+ ALOGE_IF(pthread_equal(pthread_self(), mThread),
+ "%s() destructor running in thread", __func__);
+ ALOGE_IF(mHasThread, "%s() thread never joined", __func__);
+}
+
+void OutFrameThread::setup(const char *prefix) {
+ // Name the thread with an increasing index, "prefix_#", for debugging.
+ uint32_t index = mNextThreadIndex++;
+ // Wrap the index so that we do not hit the 16 char limit
+ // and to avoid hard-to-read large numbers.
+ index = index % 100000; // arbitrary
+ snprintf(mName, sizeof(mName), "%s_%u", prefix, index);
+}
+
+void OutFrameThread::dispatch() {
+ if (mRunnable != nullptr) {
+ //androidSetThreadPriority(gettid(), ANDROID_PRIORITY_HIGHEST);
+ int ret = setpriority(PRIO_PROCESS, 0, -20);
+ if (ret < 0) {
+ ALOGE("failed to setpriority - %s err = %s", mName, strerror(errno));
+ }
+ mRunnable->run();
+ } else {
+ run();
+ }
+}
+
+// This is the entry point for the new thread created by createThread_l().
+// It converts the 'C' function call to a C++ method call.
+static void * ThreadInternal(void *arg) {
+ OutFrameThread *thread = (OutFrameThread *) arg;
+ thread->dispatch();
+ return nullptr;
+}
+
+c2_status_t OutFrameThread::start(Runnable *runnable) {
+ if (mHasThread) {
+ ALOGE("start() - mHasThread already true");
+ return C2_BAD_VALUE;
+ }
+ // mRunnable will be read by the new thread when it starts.
+ // pthread_create() forces a memory synchronization so mRunnable does not need to be atomic.
+ mRunnable = runnable;
+ int err = pthread_create(&mThread, nullptr, ThreadInternal, this);
+ if (err != 0) {
+ ALOGE("start() - pthread_create() returned %d %s", err, strerror(err));
+ return C2_BAD_VALUE;
+ } else {
+ int err = pthread_setname_np(mThread, mName);
+ ALOGW_IF((err != 0), "Could not set name of OutFrameThread. err = %d", err);
+ mHasThread = true;
+ return C2_OK;
+ }
+}
+
+c2_status_t OutFrameThread::stop() {
+ if (!mHasThread) {
+ ALOGE("stop() but no thread running");
+ return C2_BAD_VALUE;
+ }
+ // Check to see if the thread is trying to stop itself.
+ if (pthread_equal(pthread_self(), mThread)) {
+ ALOGE("%s() attempt to pthread_join() from launched thread!", __func__);
+ return C2_BAD_VALUE;
+ }
+
+ int err = pthread_join(mThread, nullptr);
+ if (err != 0) {
+ ALOGE("stop() - pthread_join() returned %d %s", err, strerror(err));
+ return C2_BAD_VALUE;
+ } else {
+ mHasThread = false;
+ return C2_OK;
+ }
+}
diff --git a/component/include/C2RKComponent.h b/component/include/C2RKComponent.h
index 8ba7ad7..3abb548 100755
--- a/component/include/C2RKComponent.h
+++ b/component/include/C2RKComponent.h
@@ -24,6 +24,8 @@
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/Mutexed.h>
#include "C2Component.h"
+#include <utils/RefBase.h>
+#include "OutFrameThread.h"
#define I2O4INDEX 0xEFFFFFFE
@@ -32,12 +34,17 @@
namespace android {
class C2RKComponent
- : public C2Component, public std::enable_shared_from_this<C2RKComponent> {
+ : public C2Component, public std::enable_shared_from_this<C2RKComponent>
+ , public Runnable, public virtual android::RefBase{
public:
explicit C2RKComponent(
const std::shared_ptr<C2ComponentInterface> &intf);
virtual ~C2RKComponent();
+ void run() override; // to implement Runnable
+ c2_status_t stopOutFrameThread();
+ bool isEncoder = false;
+ uint64_t generation;
// C2Component
// From C2Component
virtual c2_status_t setListener_vb(
@@ -56,7 +63,10 @@
// for handler
bool processQueue();
+ void processInput(std::unique_ptr<C2Work> &work,const std::shared_ptr<C2BlockPool> &pool) ;
+
protected:
+ OutFrameThread mOutFrameThread;
/**
* Initialize internal states of the component according to the config set
* in the interface.
@@ -96,6 +106,12 @@
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) = 0;
+ virtual void inputPart(
+ std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) = 0;
+
+ virtual void outputPart(
+ const std::shared_ptr<C2BlockPool> &pool) = 0;
/**
* Drain the component and finish pending work using finish().
*
@@ -127,6 +143,9 @@
std::function<void(const std::unique_ptr<C2Work> &)> fillWork,
bool delayOutput = false);
+ void finishEosWork(
+ uint64_t frameIndex, std::unique_ptr<C2Work> ¤tWork);
+
void finish(
std::unique_ptr<C2Work> &work,
std::function<void(const std::unique_ptr<C2Work> &)> fillWork);
@@ -164,6 +183,8 @@
static constexpr uint32_t NO_DRAIN = ~0u;
C2ReadView mDummyReadView;
+ // This is used by one thread to tell another thread to exit. So it must be atomic.
+ std::atomic<bool> mThreadEnabled{false};
private:
struct WorkInfo {
@@ -216,6 +237,11 @@
sp<ALooper> mLooper;
sp<WorkHandler> mHandler;
+
+ class BlockingBlockPool;
+ std::shared_ptr<BlockingBlockPool> mOutputBlockPool;
+ C2RKComponent() = delete;
+public:
class WorkQueue {
public:
typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork;
@@ -224,8 +250,8 @@
inline uint64_t generation() const { return mGeneration; }
inline void incGeneration() { ++mGeneration; mFlush = true; }
-
std::unique_ptr<C2Work> pop_front();
+
void push_back(std::unique_ptr<C2Work> work);
bool empty() const;
uint32_t drainMode() const;
@@ -250,11 +276,6 @@
PendingWork mPendingWork;
};
Mutexed<WorkQueue> mWorkQueue;
-
- class BlockingBlockPool;
- std::shared_ptr<BlockingBlockPool> mOutputBlockPool;
-
- C2RKComponent() = delete;
};
} // namespace android
diff --git a/component/include/C2RKMpiDec.h b/component/include/C2RKMpiDec.h
index 2ababb6..b34354d 100755
--- a/component/include/C2RKMpiDec.h
+++ b/component/include/C2RKMpiDec.h
@@ -44,6 +44,11 @@
void process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) override;
+ void inputPart(
+ std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) override;
+ void outputPart(
+ const std::shared_ptr<C2BlockPool> &pool) override;
c2_status_t drain(
uint32_t drainMode,
const std::shared_ptr<C2BlockPool> &pool) override;
@@ -87,7 +92,7 @@
uint32_t mVerStride;
uint32_t mTransfer;
int64_t mLastPts;
-
+ uint64_t mEosFrameIndex;
bool mStarted;
bool mFlushed;
bool mOutputEos;
@@ -95,7 +100,7 @@
bool mSignalledError;
// C2Work info, <key, value> = <frameIndex, pts>
- std::map<uint64_t, uint64_t> mWorkQueue;
+ std::map<uint64_t, uint64_t> mMpiDecWorkQueue;
/*
1. BufferMode: without surcace
diff --git a/component/include/C2RKMpiEnc.h b/component/include/C2RKMpiEnc.h
index d5d309e..1bc419f 100755
--- a/component/include/C2RKMpiEnc.h
+++ b/component/include/C2RKMpiEnc.h
@@ -42,6 +42,11 @@
void process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) override;
+ void inputPart(
+ std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) override;
+ void outputPart(
+ const std::shared_ptr<C2BlockPool> &pool) override;
c2_status_t drain(
uint32_t drainMode,
const std::shared_ptr<C2BlockPool> &pool) override;
diff --git a/component/include/OutFrameThread.h b/component/include/OutFrameThread.h
new file mode 100755
index 0000000..2d04237
--- /dev/null
+++ b/component/include/OutFrameThread.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 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 OUTFRAMETHREAD_H
+#define OUTFRAMETHREAD_H
+
+#include <atomic>
+#include <pthread.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+#include <C2AllocatorGralloc.h>
+#include <Codec2Mapper.h>
+#include "C2RKLog.h"
+#include "C2RKMediaUtils.h"
+#include "C2RKRgaDef.h"
+#include "C2RKFbcDef.h"
+#include "C2RKEnv.h"
+
+/**
+ * Abstract class similar to Java Runnable.
+ */
+class Runnable {
+public:
+ Runnable() {};
+ virtual ~Runnable() = default;
+
+ virtual void run() = 0;
+};
+
+/**
+ * Abstraction for a host dependent thread.
+ * TODO Consider using Android "Thread" class or std::thread instead.
+ */
+class OutFrameThread
+{
+public:
+ OutFrameThread();
+
+ explicit OutFrameThread(const char *prefix);
+
+ virtual ~OutFrameThread();
+
+ /**
+ * Start the thread running.
+ */
+ c2_status_t start(Runnable *runnable = nullptr);
+
+ /**
+ * Join the thread.
+ * The caller must somehow tell the thread to exit before calling join().
+ */
+ c2_status_t stop();
+
+ /**
+ * This will get called in the thread.
+ * Override this or pass a Runnable to start().
+ */
+ virtual void run() {};
+
+ void dispatch(); // called internally from 'C' thread wrapper
+
+private:
+
+ void setup(const char *prefix);
+
+ Runnable *mRunnable = nullptr;
+ bool mHasThread = false;
+ pthread_t mThread = {};
+
+ static std::atomic<uint32_t> mNextThreadIndex;
+ char mName[16]; // max length for a pthread_name
+};
+
+#endif ///OUTFRAMETHREAD_H
diff --git a/component/mpi/C2RKMpiDec.cpp b/component/mpi/C2RKMpiDec.cpp
index e58cdb1..886630a 100755
--- a/component/mpi/C2RKMpiDec.cpp
+++ b/component/mpi/C2RKMpiDec.cpp
@@ -14,26 +14,27 @@
* limitations under the License.
*/
-#undef ROCKCHIP_LOG_TAG
-#define ROCKCHIP_LOG_TAG "C2RKMpiDec"
+#undef ROCKCHIP_LOG_TAG
+#define ROCKCHIP_LOG_TAG "C2RKMpiDec"
+#include "C2RKMpiDec.h"
+
+#include <C2AllocatorGralloc.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
-#include <C2AllocatorGralloc.h>
#include <Codec2Mapper.h>
-#include <ui/GraphicBufferMapper.h>
#include <gralloc_priv_omx.h>
+#include <ui/GraphicBufferMapper.h>
-#include "hardware/hardware_rockchip.h"
-#include "hardware/gralloc_rockchip.h"
-#include "C2RKMpiDec.h"
+#include "C2RKColorAspects.h"
+#include "C2RKEnv.h"
+#include "C2RKFbcDef.h"
#include "C2RKLog.h"
#include "C2RKMediaUtils.h"
#include "C2RKRgaDef.h"
-#include "C2RKFbcDef.h"
-#include "C2RKColorAspects.h"
#include "C2RKVersion.h"
-#include "C2RKEnv.h"
+#include "hardware/gralloc_rockchip.h"
+#include "hardware/hardware_rockchip.h"
#define FLAG_NON_DISPLAY_FRAME (1u << 15)
@@ -50,29 +51,31 @@
constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
class C2RKMpiDec::IntfImpl : public C2RKInterface<void>::BaseParams {
-public:
- explicit IntfImpl(
- const std::shared_ptr<C2ReflectorHelper> &helper,
- C2String name,
- C2Component::kind_t kind,
- C2Component::domain_t domain,
- C2String mediaType)
- : C2RKInterface<void>::BaseParams(helper, name, kind, domain, mediaType) {
+ public:
+ explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper,
+ C2String name, C2Component::kind_t kind,
+ C2Component::domain_t domain, C2String mediaType)
+ : C2RKInterface<void>::BaseParams(helper, name, kind, domain,
+ mediaType) {
addParameter(
- DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
- .withDefault(new C2PortActualDelayTuning::output(kDefaultOutputDelay))
- .withFields({C2F(mActualOutputDelay, value).inRange(0, kMaxOutputDelay)})
- .withSetter(Setter<decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
+ DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
+ .withDefault(
+ new C2PortActualDelayTuning::output(kDefaultOutputDelay))
+ .withFields({C2F(mActualOutputDelay, value)
+ .inRange(0, kMaxOutputDelay)})
+ .withSetter(
+ Setter<
+ decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
.build());
- addParameter(
- DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
- .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL))
- .build());
+ addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
+ .withConstValue(new C2ComponentAttributesSetting(
+ C2Component::ATTRIB_IS_TEMPORAL))
+ .build());
// input picture frame size
addParameter(
- DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
+ DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
.withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
.withFields({
C2F(mSize, width).inRange(2, kMaxVideoWidth, 2),
@@ -81,18 +84,18 @@
.withSetter(SizeSetter)
.build());
- addParameter(
- DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
- .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
- .withFields({
- C2F(mSize, width).inRange(2, kMaxVideoWidth, 2),
- C2F(mSize, height).inRange(2, kMaxVideoWidth, 2),
- })
- .withSetter(MaxPictureSizeSetter, mSize)
- .build());
+ addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
+ .withDefault(new C2StreamMaxPictureSizeTuning::output(
+ 0u, 320, 240))
+ .withFields({
+ C2F(mSize, width).inRange(2, kMaxVideoWidth, 2),
+ C2F(mSize, height).inRange(2, kMaxVideoWidth, 2),
+ })
+ .withSetter(MaxPictureSizeSetter, mSize)
+ .build());
addParameter(
- DefineParam(mBlockSize, C2_PARAMKEY_BLOCK_SIZE)
+ DefineParam(mBlockSize, C2_PARAMKEY_BLOCK_SIZE)
.withDefault(new C2StreamBlockSizeInfo::output(0u, 320, 240))
.withFields({
C2F(mBlockSize, width).inRange(2, kMaxVideoWidth, 2),
@@ -102,139 +105,150 @@
.build());
// TODO: support more formats?
- addParameter(
- DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
- .withConstValue(new C2StreamPixelFormatInfo::output(
- 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
- .build());
+ addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
+ .withConstValue(new C2StreamPixelFormatInfo::output(
+ 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
+ .build());
// profile and level
if (mediaType == MEDIA_MIMETYPE_VIDEO_AVC) {
addParameter(
- DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withDefault(new C2StreamProfileLevelInfo::input(0u,
- C2Config::PROFILE_AVC_BASELINE, C2Config::LEVEL_AVC_5_1))
- .withFields({
- C2F(mProfileLevel, profile).oneOf({
- C2Config::PROFILE_AVC_CONSTRAINED_BASELINE,
- C2Config::PROFILE_AVC_BASELINE,
- C2Config::PROFILE_AVC_MAIN,
- C2Config::PROFILE_AVC_CONSTRAINED_HIGH,
- C2Config::PROFILE_AVC_PROGRESSIVE_HIGH,
- C2Config::PROFILE_AVC_HIGH}),
- C2F(mProfileLevel, level).oneOf({
- C2Config::LEVEL_AVC_1, C2Config::LEVEL_AVC_1B, C2Config::LEVEL_AVC_1_1,
- C2Config::LEVEL_AVC_1_2, C2Config::LEVEL_AVC_1_3,
- C2Config::LEVEL_AVC_2, C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2,
- C2Config::LEVEL_AVC_3, C2Config::LEVEL_AVC_3_1, C2Config::LEVEL_AVC_3_2,
- C2Config::LEVEL_AVC_4, C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2,
- C2Config::LEVEL_AVC_5, C2Config::LEVEL_AVC_5_1, C2Config::LEVEL_AVC_5_2})
- })
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(
+ 0u, C2Config::PROFILE_AVC_BASELINE,
+ C2Config::LEVEL_AVC_5_1))
+ .withFields(
+ {C2F(mProfileLevel, profile)
+ .oneOf({C2Config::PROFILE_AVC_CONSTRAINED_BASELINE,
+ C2Config::PROFILE_AVC_BASELINE,
+ C2Config::PROFILE_AVC_MAIN,
+ C2Config::PROFILE_AVC_CONSTRAINED_HIGH,
+ C2Config::PROFILE_AVC_PROGRESSIVE_HIGH,
+ C2Config::PROFILE_AVC_HIGH}),
+ C2F(mProfileLevel, level)
+ .oneOf({C2Config::LEVEL_AVC_1,
+ C2Config::LEVEL_AVC_1B,
+ C2Config::LEVEL_AVC_1_1,
+ C2Config::LEVEL_AVC_1_2,
+ C2Config::LEVEL_AVC_1_3,
+ C2Config::LEVEL_AVC_2,
+ C2Config::LEVEL_AVC_2_1,
+ C2Config::LEVEL_AVC_2_2,
+ C2Config::LEVEL_AVC_3,
+ C2Config::LEVEL_AVC_3_1,
+ C2Config::LEVEL_AVC_3_2,
+ C2Config::LEVEL_AVC_4,
+ C2Config::LEVEL_AVC_4_1,
+ C2Config::LEVEL_AVC_4_2,
+ C2Config::LEVEL_AVC_5,
+ C2Config::LEVEL_AVC_5_1,
+ C2Config::LEVEL_AVC_5_2})})
.withSetter(ProfileLevelSetter, mSize)
.build());
} else if (mediaType == MEDIA_MIMETYPE_VIDEO_HEVC) {
addParameter(
- DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withDefault(new C2StreamProfileLevelInfo::input(0u,
- C2Config::PROFILE_HEVC_MAIN, C2Config::LEVEL_HEVC_MAIN_5_1))
- .withFields({
- C2F(mProfileLevel, profile).oneOf({
- C2Config::PROFILE_HEVC_MAIN,
- C2Config::PROFILE_HEVC_MAIN_10}),
- C2F(mProfileLevel, level).oneOf({
- C2Config::LEVEL_HEVC_MAIN_1,
- C2Config::LEVEL_HEVC_MAIN_2, C2Config::LEVEL_HEVC_MAIN_2_1,
- C2Config::LEVEL_HEVC_MAIN_3, C2Config::LEVEL_HEVC_MAIN_3_1,
- C2Config::LEVEL_HEVC_MAIN_4, C2Config::LEVEL_HEVC_MAIN_4_1,
- C2Config::LEVEL_HEVC_MAIN_5, C2Config::LEVEL_HEVC_MAIN_5_1,
- C2Config::LEVEL_HEVC_MAIN_5_2, C2Config::LEVEL_HEVC_HIGH_4,
- C2Config::LEVEL_HEVC_HIGH_4_1, C2Config::LEVEL_HEVC_HIGH_5,
- C2Config::LEVEL_HEVC_HIGH_5_1})
- })
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(
+ 0u, C2Config::PROFILE_HEVC_MAIN,
+ C2Config::LEVEL_HEVC_MAIN_5_1))
+ .withFields({C2F(mProfileLevel, profile)
+ .oneOf({C2Config::PROFILE_HEVC_MAIN,
+ C2Config::PROFILE_HEVC_MAIN_10}),
+ C2F(mProfileLevel, level)
+ .oneOf({C2Config::LEVEL_HEVC_MAIN_1,
+ C2Config::LEVEL_HEVC_MAIN_2,
+ C2Config::LEVEL_HEVC_MAIN_2_1,
+ C2Config::LEVEL_HEVC_MAIN_3,
+ C2Config::LEVEL_HEVC_MAIN_3_1,
+ C2Config::LEVEL_HEVC_MAIN_4,
+ C2Config::LEVEL_HEVC_MAIN_4_1,
+ C2Config::LEVEL_HEVC_MAIN_5,
+ C2Config::LEVEL_HEVC_MAIN_5_1,
+ C2Config::LEVEL_HEVC_MAIN_5_2,
+ C2Config::LEVEL_HEVC_HIGH_4,
+ C2Config::LEVEL_HEVC_HIGH_4_1,
+ C2Config::LEVEL_HEVC_HIGH_5,
+ C2Config::LEVEL_HEVC_HIGH_5_1})})
.withSetter(ProfileLevelSetter, mSize)
.build());
} else if (mediaType == MEDIA_MIMETYPE_VIDEO_MPEG2) {
addParameter(
- DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withDefault(new C2StreamProfileLevelInfo::input(0u,
- C2Config::PROFILE_MP2V_SIMPLE, C2Config::LEVEL_MP2V_HIGH))
- .withFields({
- C2F(mProfileLevel, profile).oneOf({
- C2Config::PROFILE_MP2V_SIMPLE,
- C2Config::PROFILE_MP2V_MAIN}),
- C2F(mProfileLevel, level).oneOf({
- C2Config::LEVEL_MP2V_LOW,
- C2Config::LEVEL_MP2V_MAIN,
- C2Config::LEVEL_MP2V_HIGH_1440,
- C2Config::LEVEL_MP2V_HIGH})
- })
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(
+ 0u, C2Config::PROFILE_MP2V_SIMPLE,
+ C2Config::LEVEL_MP2V_HIGH))
+ .withFields({C2F(mProfileLevel, profile)
+ .oneOf({C2Config::PROFILE_MP2V_SIMPLE,
+ C2Config::PROFILE_MP2V_MAIN}),
+ C2F(mProfileLevel, level)
+ .oneOf({C2Config::LEVEL_MP2V_LOW,
+ C2Config::LEVEL_MP2V_MAIN,
+ C2Config::LEVEL_MP2V_HIGH_1440,
+ C2Config::LEVEL_MP2V_HIGH})})
.withSetter(ProfileLevelSetter, mSize)
.build());
} else if (mediaType == MEDIA_MIMETYPE_VIDEO_MPEG4) {
addParameter(
- DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withDefault(new C2StreamProfileLevelInfo::input(0u,
- C2Config::PROFILE_MP4V_SIMPLE, C2Config::LEVEL_MP4V_3))
- .withFields({
- C2F(mProfileLevel, profile).oneOf({
- C2Config::PROFILE_MP4V_SIMPLE}),
- C2F(mProfileLevel, level).oneOf({
- C2Config::LEVEL_MP4V_0,
- C2Config::LEVEL_MP4V_0B,
- C2Config::LEVEL_MP4V_1,
- C2Config::LEVEL_MP4V_2,
- C2Config::LEVEL_MP4V_3})
- })
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(
+ 0u, C2Config::PROFILE_MP4V_SIMPLE,
+ C2Config::LEVEL_MP4V_3))
+ .withFields({C2F(mProfileLevel, profile)
+ .oneOf({C2Config::PROFILE_MP4V_SIMPLE}),
+ C2F(mProfileLevel, level)
+ .oneOf({C2Config::LEVEL_MP4V_0,
+ C2Config::LEVEL_MP4V_0B,
+ C2Config::LEVEL_MP4V_1,
+ C2Config::LEVEL_MP4V_2,
+ C2Config::LEVEL_MP4V_3})})
.withSetter(ProfileLevelSetter, mSize)
.build());
} else if (mediaType == MEDIA_MIMETYPE_VIDEO_H263) {
addParameter(
- DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withDefault(new C2StreamProfileLevelInfo::input(0u,
- C2Config::PROFILE_H263_BASELINE, C2Config::LEVEL_H263_30))
- .withFields({
- C2F(mProfileLevel, profile).oneOf({
- C2Config::PROFILE_H263_BASELINE,
- C2Config::PROFILE_H263_ISWV2}),
- C2F(mProfileLevel, level).oneOf({
- C2Config::LEVEL_H263_10,
- C2Config::LEVEL_H263_20,
- C2Config::LEVEL_H263_30,
- C2Config::LEVEL_H263_40,
- C2Config::LEVEL_H263_45})
- })
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(
+ 0u, C2Config::PROFILE_H263_BASELINE,
+ C2Config::LEVEL_H263_30))
+ .withFields({C2F(mProfileLevel, profile)
+ .oneOf({C2Config::PROFILE_H263_BASELINE,
+ C2Config::PROFILE_H263_ISWV2}),
+ C2F(mProfileLevel, level)
+ .oneOf({C2Config::LEVEL_H263_10,
+ C2Config::LEVEL_H263_20,
+ C2Config::LEVEL_H263_30,
+ C2Config::LEVEL_H263_40,
+ C2Config::LEVEL_H263_45})})
.withSetter(ProfileLevelSetter, mSize)
.build());
} else if (mediaType == MEDIA_MIMETYPE_VIDEO_VP9) {
addParameter(
- DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withDefault(new C2StreamProfileLevelInfo::input(0u,
- C2Config::PROFILE_VP9_0, C2Config::LEVEL_VP9_5))
- .withFields({
- C2F(mProfileLevel, profile).oneOf({
- C2Config::PROFILE_VP9_0,
- C2Config::PROFILE_VP9_2}),
- C2F(mProfileLevel, level).oneOf({
- C2Config::LEVEL_VP9_1,
- C2Config::LEVEL_VP9_1_1,
- C2Config::LEVEL_VP9_2,
- C2Config::LEVEL_VP9_2_1,
- C2Config::LEVEL_VP9_3,
- C2Config::LEVEL_VP9_3_1,
- C2Config::LEVEL_VP9_4,
- C2Config::LEVEL_VP9_4_1,
- C2Config::LEVEL_VP9_5})
- })
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(
+ 0u, C2Config::PROFILE_VP9_0, C2Config::LEVEL_VP9_5))
+ .withFields({C2F(mProfileLevel, profile)
+ .oneOf({C2Config::PROFILE_VP9_0,
+ C2Config::PROFILE_VP9_2}),
+ C2F(mProfileLevel, level)
+ .oneOf({C2Config::LEVEL_VP9_1,
+ C2Config::LEVEL_VP9_1_1,
+ C2Config::LEVEL_VP9_2,
+ C2Config::LEVEL_VP9_2_1,
+ C2Config::LEVEL_VP9_3,
+ C2Config::LEVEL_VP9_3_1,
+ C2Config::LEVEL_VP9_4,
+ C2Config::LEVEL_VP9_4_1,
+ C2Config::LEVEL_VP9_5})})
.withSetter(ProfileLevelSetter, mSize)
.build());
} else if (mediaType == MEDIA_MIMETYPE_VIDEO_VP8) {
// TODO
- }
+ }
// max input buffer size
addParameter(
- DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
- .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
+ DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
+ .withDefault(new C2StreamMaxBufferSizeInfo::input(
+ 0u, kMinInputBufferSize))
.withFields({
C2F(mMaxInputSize, value).any(),
})
@@ -242,39 +256,41 @@
.build());
// ColorInfo
- C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() };
+ C2ChromaOffsetStruct locations[1] = {
+ C2ChromaOffsetStruct::ITU_YUV_420_0()};
std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
- C2StreamColorInfo::output::AllocShared(
- 1u, 0u, 8u /* bitDepth */, C2Color::YUV_420);
+ C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
+ C2Color::YUV_420);
memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
- defaultColorInfo =
- C2StreamColorInfo::output::AllocShared(
- { C2ChromaOffsetStruct::ITU_YUV_420_0() },
- 0u, 8u /* bitDepth */, C2Color::YUV_420);
+ defaultColorInfo = C2StreamColorInfo::output::AllocShared(
+ {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
+ C2Color::YUV_420);
helper->addStructDescriptors<C2ChromaOffsetStruct>();
- addParameter(
- DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
- .withConstValue(defaultColorInfo)
- .build());
+ addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
+ .withConstValue(defaultColorInfo)
+ .build());
// colorAspects
addParameter(
- DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
+ DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
.withDefault(new C2StreamColorAspectsTuning::output(
- 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
- C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
- .withFields({
- C2F(mDefaultColorAspects, range).inRange(
- C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
- C2F(mDefaultColorAspects, primaries).inRange(
- C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
- C2F(mDefaultColorAspects, transfer).inRange(
- C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
- C2F(mDefaultColorAspects, matrix).inRange(
- C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
- })
+ 0u, C2Color::RANGE_UNSPECIFIED,
+ C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({C2F(mDefaultColorAspects, range)
+ .inRange(C2Color::RANGE_UNSPECIFIED,
+ C2Color::RANGE_OTHER),
+ C2F(mDefaultColorAspects, primaries)
+ .inRange(C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::PRIMARIES_OTHER),
+ C2F(mDefaultColorAspects, transfer)
+ .inRange(C2Color::TRANSFER_UNSPECIFIED,
+ C2Color::TRANSFER_OTHER),
+ C2F(mDefaultColorAspects, matrix)
+ .inRange(C2Color::MATRIX_UNSPECIFIED,
+ C2Color::MATRIX_OTHER)})
.withSetter(DefaultColorAspectsSetter)
.build());
@@ -283,44 +299,54 @@
mediaType == MEDIA_MIMETYPE_VIDEO_HEVC ||
mediaType == MEDIA_MIMETYPE_VIDEO_MPEG2) {
addParameter(
- DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+ DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
.withDefault(new C2StreamColorAspectsInfo::input(
- 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
- C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
- .withFields({
- C2F(mCodedColorAspects, range).inRange(
- C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
- C2F(mCodedColorAspects, primaries).inRange(
- C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
- C2F(mCodedColorAspects, transfer).inRange(
- C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
- C2F(mCodedColorAspects, matrix).inRange(
- C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
- })
+ 0u, C2Color::RANGE_LIMITED,
+ C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED,
+ C2Color::MATRIX_UNSPECIFIED))
+ .withFields({C2F(mCodedColorAspects, range)
+ .inRange(C2Color::RANGE_UNSPECIFIED,
+ C2Color::RANGE_OTHER),
+ C2F(mCodedColorAspects, primaries)
+ .inRange(C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::PRIMARIES_OTHER),
+ C2F(mCodedColorAspects, transfer)
+ .inRange(C2Color::TRANSFER_UNSPECIFIED,
+ C2Color::TRANSFER_OTHER),
+ C2F(mCodedColorAspects, matrix)
+ .inRange(C2Color::MATRIX_UNSPECIFIED,
+ C2Color::MATRIX_OTHER)})
.withSetter(CodedColorAspectsSetter)
.build());
- addParameter(
- DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+ addParameter(
+ DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
.withDefault(new C2StreamColorAspectsInfo::output(
- 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
- C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
- .withFields({
- C2F(mColorAspects, range).inRange(
- C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
- C2F(mColorAspects, primaries).inRange(
- C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
- C2F(mColorAspects, transfer).inRange(
- C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
- C2F(mColorAspects, matrix).inRange(
- C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
- })
- .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
+ 0u, C2Color::RANGE_UNSPECIFIED,
+ C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED,
+ C2Color::MATRIX_UNSPECIFIED))
+ .withFields({C2F(mColorAspects, range)
+ .inRange(C2Color::RANGE_UNSPECIFIED,
+ C2Color::RANGE_OTHER),
+ C2F(mColorAspects, primaries)
+ .inRange(C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::PRIMARIES_OTHER),
+ C2F(mColorAspects, transfer)
+ .inRange(C2Color::TRANSFER_UNSPECIFIED,
+ C2Color::TRANSFER_OTHER),
+ C2F(mColorAspects, matrix)
+ .inRange(C2Color::MATRIX_UNSPECIFIED,
+ C2Color::MATRIX_OTHER)})
+ .withSetter(ColorAspectsSetter, mDefaultColorAspects,
+ mCodedColorAspects)
.build());
}
}
- static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe,
+ static C2R SizeSetter(bool mayBlock,
+ const C2P<C2StreamPictureSizeInfo::output> &oldMe,
C2P<C2StreamPictureSizeInfo::output> &me) {
(void)mayBlock;
C2R res = C2R::Ok();
@@ -332,28 +358,37 @@
res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
me.set().height = oldMe.v.height;
}
- if (me.set().width * me.set().height > kMaxVideoWidth * kMaxVideoHeight) {
+ if (me.set().width * me.set().height >
+ kMaxVideoWidth * kMaxVideoHeight) {
c2_warn("max support video resolution %dx%d, cur %dx%d",
- kMaxVideoWidth, kMaxVideoHeight, me.set().width, me.set().height);
+ kMaxVideoWidth, kMaxVideoHeight, me.set().width,
+ me.set().height);
}
return res;
}
- static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me,
- const C2P<C2StreamPictureSizeInfo::output> &size) {
+ static C2R MaxPictureSizeSetter(
+ bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me,
+ const C2P<C2StreamPictureSizeInfo::output> &size) {
(void)mayBlock;
- // TODO: get max width/height from the size's field helpers vs. hardcoding
- me.set().width = c2_min(c2_max(me.v.width, size.v.width), kMaxVideoWidth);
- me.set().height = c2_min(c2_max(me.v.height, size.v.height), kMaxVideoWidth);
- if (me.set().width * me.set().height > kMaxVideoWidth * kMaxVideoHeight) {
+ // TODO: get max width/height from the size's field helpers vs.
+ // hardcoding
+ me.set().width =
+ c2_min(c2_max(me.v.width, size.v.width), kMaxVideoWidth);
+ me.set().height =
+ c2_min(c2_max(me.v.height, size.v.height), kMaxVideoWidth);
+ if (me.set().width * me.set().height >
+ kMaxVideoWidth * kMaxVideoHeight) {
c2_warn("max support video resolution %dx%d, cur %dx%d",
- kMaxVideoWidth, kMaxVideoHeight, me.set().width, me.set().height);
+ kMaxVideoWidth, kMaxVideoHeight, me.set().width,
+ me.set().height);
}
return C2R::Ok();
}
- static C2R BlockSizeSetter(bool mayBlock, const C2P<C2StreamBlockSizeInfo::output> &oldMe,
- C2P<C2StreamBlockSizeInfo::output> &me) {
+ static C2R BlockSizeSetter(bool mayBlock,
+ const C2P<C2StreamBlockSizeInfo::output> &oldMe,
+ C2P<C2StreamBlockSizeInfo::output> &me) {
(void)mayBlock;
C2R res = C2R::Ok();
if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
@@ -367,69 +402,79 @@
return res;
}
- static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
- const C2P<C2StreamPictureSizeInfo::output> &size) {
+ static C2R ProfileLevelSetter(
+ bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
+ const C2P<C2StreamPictureSizeInfo::output> &size) {
(void)mayBlock;
(void)size;
(void)me; // TODO: validate
return C2R::Ok();
}
- static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
- const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
+ static C2R MaxInputSizeSetter(
+ bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
+ const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
(void)mayBlock;
// assume compression ratio of 2
- me.set().value = c2_max((((maxSize.v.width + 63) / 64)
- * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
+ me.set().value = c2_max((((maxSize.v.width + 63) / 64) *
+ ((maxSize.v.height + 63) / 64) * 3072),
+ kMinInputBufferSize);
return C2R::Ok();
}
-
- static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
+ static C2R DefaultColorAspectsSetter(
+ bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
(void)mayBlock;
if (me.v.range > C2Color::RANGE_OTHER) {
- me.set().range = C2Color::RANGE_OTHER;
+ me.set().range = C2Color::RANGE_OTHER;
}
if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
- me.set().primaries = C2Color::PRIMARIES_OTHER;
+ me.set().primaries = C2Color::PRIMARIES_OTHER;
}
if (me.v.transfer > C2Color::TRANSFER_OTHER) {
- me.set().transfer = C2Color::TRANSFER_OTHER;
+ me.set().transfer = C2Color::TRANSFER_OTHER;
}
if (me.v.matrix > C2Color::MATRIX_OTHER) {
- me.set().matrix = C2Color::MATRIX_OTHER;
+ me.set().matrix = C2Color::MATRIX_OTHER;
}
return C2R::Ok();
}
- static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
+ static C2R CodedColorAspectsSetter(
+ bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
(void)mayBlock;
if (me.v.range > C2Color::RANGE_OTHER) {
- me.set().range = C2Color::RANGE_OTHER;
+ me.set().range = C2Color::RANGE_OTHER;
}
if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
- me.set().primaries = C2Color::PRIMARIES_OTHER;
+ me.set().primaries = C2Color::PRIMARIES_OTHER;
}
if (me.v.transfer > C2Color::TRANSFER_OTHER) {
- me.set().transfer = C2Color::TRANSFER_OTHER;
+ me.set().transfer = C2Color::TRANSFER_OTHER;
}
if (me.v.matrix > C2Color::MATRIX_OTHER) {
- me.set().matrix = C2Color::MATRIX_OTHER;
+ me.set().matrix = C2Color::MATRIX_OTHER;
}
return C2R::Ok();
}
- static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
- const C2P<C2StreamColorAspectsTuning::output> &def,
- const C2P<C2StreamColorAspectsInfo::input> &coded) {
+ static C2R ColorAspectsSetter(
+ bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+ const C2P<C2StreamColorAspectsTuning::output> &def,
+ const C2P<C2StreamColorAspectsInfo::input> &coded) {
(void)mayBlock;
- // take default values for all unspecified fields, and coded values for specified ones
- me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
+ // take default values for all unspecified fields, and coded values for
+ // specified ones
+ me.set().range =
+ coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
- ? def.v.primaries : coded.v.primaries;
+ ? def.v.primaries
+ : coded.v.primaries;
me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
- ? def.v.transfer : coded.v.transfer;
- me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
+ ? def.v.transfer
+ : coded.v.transfer;
+ me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix
+ : coded.v.matrix;
return C2R::Ok();
}
@@ -441,10 +486,12 @@
return mColorAspects;
}
- std::shared_ptr<C2StreamColorAspectsTuning::output> getDefaultColorAspects_l() {
+ std::shared_ptr<C2StreamColorAspectsTuning::output>
+ getDefaultColorAspects_l() {
return mDefaultColorAspects;
}
-private:
+
+ private:
std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
std::shared_ptr<C2StreamBlockSizeInfo::output> mBlockSize;
@@ -457,11 +504,10 @@
std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
};
-C2RKMpiDec::C2RKMpiDec(
- const char *name,
- c2_node_id_t id,
- const std::shared_ptr<IntfImpl> &intfImpl)
- : C2RKComponent(std::make_shared<C2RKInterface<IntfImpl>>(name, id, intfImpl)),
+C2RKMpiDec::C2RKMpiDec(const char *name, c2_node_id_t id,
+ const std::shared_ptr<IntfImpl> &intfImpl)
+ : C2RKComponent(
+ std::make_shared<C2RKInterface<IntfImpl>>(name, id, intfImpl)),
mIntf(intfImpl),
mMppCtx(nullptr),
mMppMpi(nullptr),
@@ -473,6 +519,7 @@
mHorStride(0),
mVerStride(0),
mLastPts(-1),
+ mEosFrameIndex(-1),
mStarted(false),
mFlushed(false),
mOutputEos(false),
@@ -543,7 +590,7 @@
mSignalledInputEos = false;
mSignalledError = false;
- mWorkQueue.clear();
+ mMpiDecWorkQueue.clear();
clearOutBuffers();
if (mFrmGrp) {
@@ -554,7 +601,6 @@
}
mFlushed = true;
-
return ret;
}
@@ -598,19 +644,20 @@
mMppMpi->control(mMppCtx, MPP_DEC_SET_ENABLE_FAST_PLAY, &fastPlay);
}
-
{
- MppFrame frame = nullptr;
+ MppFrame frame = nullptr;
uint32_t mppFmt = mColorFormat;
/* user can't process fbc output on bufferMode */
/* SMPTEST2084 = 6*/
- if ((mTransfer == 6) || (!mBufferMode && (mWidth * mHeight > 1920 * 1080))) {
+ if ((mTransfer == 6) ||
+ (!mBufferMode && (mWidth * mHeight > 1920 * 1080))) {
mFbcCfg.mode = C2RKFbcDef::getFbcOutputMode(mCodingType);
if (mFbcCfg.mode) {
c2_info("use mpp fbc output mode");
mppFmt |= MPP_FRAME_FBC_AFBC_V2;
- mMppMpi->control(mMppCtx, MPP_DEC_SET_OUTPUT_FORMAT, (MppParam)&mppFmt);
+ mMppMpi->control(mMppCtx, MPP_DEC_SET_OUTPUT_FORMAT,
+ (MppParam)&mppFmt);
}
} else {
mFbcCfg.mode = 0;
@@ -628,8 +675,7 @@
* info-change will sent to transmit correct stride.
*/
if (mpp_frame_get_hor_stride(frame) <= 0 ||
- mpp_frame_get_ver_stride(frame) <= 0)
- {
+ mpp_frame_get_ver_stride(frame) <= 0) {
mpp_frame_set_hor_stride(frame, mWidth);
mpp_frame_set_ver_stride(frame, mHeight);
mMppMpi->control(mMppCtx, MPP_DEC_SET_FRAME_INFO, (MppParam)frame);
@@ -659,10 +705,10 @@
/* fbc decode output has padding inside, set crop before display */
if (mFbcCfg.mode) {
- C2RKFbcDef::getFbcOutputOffset(mCodingType,
- &mFbcCfg.paddingX,
+ C2RKFbcDef::getFbcOutputOffset(mCodingType, &mFbcCfg.paddingX,
&mFbcCfg.paddingY);
- c2_info("fbc padding offset(%d, %d)", mFbcCfg.paddingX, mFbcCfg.paddingY);
+ c2_info("fbc padding offset(%d, %d)", mFbcCfg.paddingX,
+ mFbcCfg.paddingY);
}
mStarted = true;
@@ -694,22 +740,20 @@
work->workletsProcessed = 1u;
}
-void C2RKMpiDec::finishWork(
- uint64_t index,
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2GraphicBlock> block,
- bool delayOutput) {
+void C2RKMpiDec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2GraphicBlock> block,
+ bool delayOutput) {
+ (void)delayOutput;
if (!block) {
c2_err("empty block index %d", index);
return;
}
uint32_t left = mFbcCfg.mode ? mFbcCfg.paddingX : 0;
- uint32_t top = mFbcCfg.mode ? mFbcCfg.paddingY : 0;
+ uint32_t top = mFbcCfg.mode ? mFbcCfg.paddingY : 0;
- std::shared_ptr<C2Buffer> buffer
- = createGraphicBuffer(std::move(block),
- C2Rect(mWidth, mHeight).at(left, top));
+ std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(
+ std::move(block), C2Rect(mWidth, mHeight).at(left, top));
mOutBlock = nullptr;
@@ -725,11 +769,11 @@
class FillWork {
public:
FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
- const std::shared_ptr<C2Buffer>& buffer)
+ const std::shared_ptr<C2Buffer> &buffer)
: mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {}
~FillWork() = default;
- void operator()(const std::unique_ptr<C2Work>& work) {
+ void operator()(const std::unique_ptr<C2Work> &work) {
work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
work->worklets.front()->output.buffers.clear();
work->worklets.front()->output.ordinal = mOrdinal;
@@ -768,17 +812,16 @@
buffer.reset();
}
} else {
- fillWork(work);
+ cloneAndSend(index, work, fillWork);
}
} else {
- finish(index, fillWork, delayOutput);
+ cloneAndSend(index, work, fillWork);
}
}
-c2_status_t C2RKMpiDec::drainInternal(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool,
- const std::unique_ptr<C2Work> &work) {
+c2_status_t C2RKMpiDec::drainInternal(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool> &pool,
+ const std::unique_ptr<C2Work> &work) {
c2_info_f("in");
if (drainMode == NO_DRAIN) {
@@ -795,7 +838,7 @@
uint32_t kMaxRetryNum = 20;
uint32_t retry = 0;
- while (true){
+ while (true) {
ret = ensureDecoderState(pool);
if (ret != C2_OK) {
mSignalledError = true;
@@ -818,7 +861,7 @@
mOutputEos = true;
c2_warn("drain: eos not found, force set output EOS.");
} else {
- usleep(5 * 1000);
+ usleep(1000);
}
}
@@ -827,15 +870,18 @@
return C2_OK;
}
-c2_status_t C2RKMpiDec::drain(
- uint32_t drainMode,
- const std::shared_ptr<C2BlockPool> &pool) {
+c2_status_t C2RKMpiDec::drain(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool> &pool) {
return drainInternal(drainMode, pool, nullptr);
}
-void C2RKMpiDec::process(
- const std::unique_ptr<C2Work> &work,
- const std::shared_ptr<C2BlockPool> &pool) {
+void C2RKMpiDec::process(const std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) {
+ (void)work;
+ (void)pool;
+}
+void C2RKMpiDec::inputPart(std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) {
c2_status_t err = C2_OK;
// Initialize output work
@@ -865,7 +911,8 @@
size_t inSize = 0u;
C2ReadView rView = mDummyReadView;
if (!work->input.buffers.empty()) {
- rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
+ rView =
+ work->input.buffers[0]->data().linearBlocks().front().map().get();
inData = const_cast<uint8_t *>(rView.data());
inSize = rView.capacity();
if (inSize && rView.error()) {
@@ -879,14 +926,11 @@
uint64_t frameIndex = work->input.ordinal.frameIndex.peekull();
uint64_t timestamp = work->input.ordinal.timestamp.peekll();
- c2_trace("in buffer attr. size %zu timestamp %lld frameindex %lld, flags %x",
- inSize, timestamp, frameIndex, flags);
+ c2_trace(
+ "in buffer attr. size %zu timestamp %lld frameindex %lld, flags %x",
+ inSize, timestamp, frameIndex, flags);
bool eos = ((flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
- bool hasPicture = false;
- bool delayOutput = false;
- uint32_t outfrmCnt = 0;
- OutWorkEntry entry;
err = ensureDecoderState(pool);
if (err != C2_OK) {
@@ -900,7 +944,8 @@
err = sendpacket(inData, inSize, frameIndex, timestamp, flags);
if (err != C2_OK) {
c2_warn("failed to enqueue packet, pts %lld", timestamp);
- } else if (flags & (C2FrameData::FLAG_CODEC_CONFIG | FLAG_NON_DISPLAY_FRAME)) {
+ } else if (flags &
+ (C2FrameData::FLAG_CODEC_CONFIG | FLAG_NON_DISPLAY_FRAME)) {
fillEmptyWork(work);
} else {
if (inSize == 0 && !eos) {
@@ -917,37 +962,56 @@
}
}
}
+}
-outframe:
- if (!eos) {
- err = getoutframe(&entry);
- if (err == C2_OK) {
- outfrmCnt++;
- hasPicture = true;
- } else if (err == C2_CORRUPTED) {
- mSignalledError = true;
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
+void C2RKMpiDec::outputPart(const std::shared_ptr<C2BlockPool> &pool) {
+ (void)pool;
+ c2_status_t err = C2_OK;
+ bool hasPicture = false;
+
+ uint32_t outfrmCnt = 0;
+ OutWorkEntry entry;
+
+ err = getoutframe(&entry);
+ if (err == C2_OK) {
+ outfrmCnt++;
+ hasPicture = true;
+ } else if (err == C2_CORRUPTED) {
+ mSignalledError = true;
+ return;
+ } else if (err == C2_NO_MEMORY) {
+ err = ensureDecoderState(pool);
+ }
+
+ if (mOutputEos) {
+ c2_trace("mOutputEos true");
+ // drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
+ if (entry.frameIndex == mEosFrameIndex) {
+ Mutexed<WorkQueue>::Locked queue(mWorkQueue);
+
+ if (queue->pending().count(entry.frameIndex) != 0) {
+ std::unique_ptr<C2Work> work;
+ work = std::move(queue->pending().at(entry.frameIndex));
+ queue->pending().erase(entry.frameIndex);
+ queue.unlock();
+ fillEmptyWork(work);
+ finishEosWork(mEosFrameIndex, work);
+ }
return;
}
}
-
- if (eos) {
- drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
- mSignalledInputEos = true;
- } else if (hasPicture) {
- finishWork(entry.frameIndex, work, entry.outblock, delayOutput);
- /* Avoid stock frame, continue to search available output */
- ensureDecoderState(pool);
- hasPicture = false;
-
- /* output pending work after the C2Work in process return. It is
- neccessary to output work sequentially, otherwise the output
- captured by the user may be discontinuous */
- if (entry.frameIndex == frameIndex) {
- delayOutput = true;
+ if (hasPicture) {
+ Mutexed<WorkQueue>::Locked queue(mWorkQueue);
+ if (queue->pending().count(entry.frameIndex) != 0) {
+ std::unique_ptr<C2Work> work;
+ work = std::move(queue->pending().at(entry.frameIndex));
+ queue->pending().erase(entry.frameIndex);
+ queue.unlock();
+ finishWork(entry.frameIndex, work, entry.outblock, false);
}
- goto outframe;
+
+ hasPicture = false;
+ return;
} else if (outfrmCnt == 0) {
usleep(1000);
}
@@ -957,8 +1021,8 @@
VuiColorAspects aspects;
aspects.primaries = mpp_frame_get_color_primaries(frame);
- aspects.transfer = mpp_frame_get_color_trc(frame);
- aspects.coeffs = mpp_frame_get_colorspace(frame);
+ aspects.transfer = mpp_frame_get_color_trc(frame);
+ aspects.coeffs = mpp_frame_get_colorspace(frame);
if (mCodingType == MPP_VIDEO_CodingMPEG2) {
aspects.fullRange = 0;
} else {
@@ -970,11 +1034,11 @@
if (!(aspects == mBitstreamColorAspects)) {
mBitstreamColorAspects = aspects;
ColorAspects sfAspects;
- C2StreamColorAspectsInfo::input codedAspects = { 0u };
+ C2StreamColorAspectsInfo::input codedAspects = {0u};
ColorUtils::convertIsoColorAspectsToCodecAspects(
- aspects.primaries, aspects.transfer, aspects.coeffs,
- aspects.fullRange, sfAspects);
+ aspects.primaries, aspects.transfer, aspects.coeffs,
+ aspects.fullRange, sfAspects);
if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
@@ -992,13 +1056,14 @@
mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
c2_trace("VuiColorAspects: pri %d tra %d coeff %d range %d",
- aspects.primaries, aspects.transfer,
- aspects.coeffs, aspects.fullRange);
+ aspects.primaries, aspects.transfer, aspects.coeffs,
+ aspects.fullRange);
}
}
-c2_status_t C2RKMpiDec::sendpacket(
- uint8_t *data, size_t size, uint64_t frmIndex, uint64_t pts, uint32_t flags) {
+c2_status_t C2RKMpiDec::sendpacket(uint8_t *data, size_t size,
+ uint64_t frmIndex, uint64_t pts,
+ uint32_t flags) {
c2_status_t ret = C2_OK;
MppPacket packet = nullptr;
@@ -1009,6 +1074,7 @@
if (flags & C2FrameData::FLAG_END_OF_STREAM) {
c2_info("send input eos");
+ mEosFrameIndex = frmIndex;
mpp_packet_set_eos(packet);
}
@@ -1024,8 +1090,9 @@
err = mMppMpi->decode_put_packet(mMppCtx, packet);
if (err == MPP_OK) {
c2_trace("send packet pts %lld size %d", pts, size);
- if (!(flags & (C2FrameData::FLAG_CODEC_CONFIG | FLAG_NON_DISPLAY_FRAME))) {
- mWorkQueue.insert(std::make_pair(frmIndex, pts));
+ if (!(flags &
+ (C2FrameData::FLAG_CODEC_CONFIG | FLAG_NON_DISPLAY_FRAME))) {
+ mMpiDecWorkQueue.insert(std::make_pair(frmIndex, pts));
}
break;
}
@@ -1034,7 +1101,7 @@
ret = C2_CORRUPTED;
break;
}
- usleep(5 * 1000);
+ usleep(1000);
}
mpp_packet_deinit(&packet);
@@ -1047,24 +1114,33 @@
MPP_RET err = MPP_OK;
MppFrame frame = nullptr;
+ uint32_t isEos = 0;
uint64_t outIndex = 0;
+ if (mFlushed) return C2_NOT_FOUND;
+
std::shared_ptr<C2GraphicBlock> outblock = nullptr;
-
- err = mMppMpi->decode_get_frame(mMppCtx, &frame);
- if (MPP_OK != err || !frame) {
- return C2_NOT_FOUND;
+ while (mThreadEnabled.load()) {
+ err = mMppMpi->decode_get_frame(mMppCtx, &frame);
+ if (MPP_OK != err || !frame) {
+ usleep(1000);
+ } else if (MPP_OK == err && frame) {
+ break;
+ } else {
+ return C2_NOT_FOUND;
+ }
}
-
- uint32_t width = mpp_frame_get_width(frame);
+ if (!mThreadEnabled.load())
+ return C2_NOT_FOUND;
+ uint32_t width = mpp_frame_get_width(frame);
uint32_t height = mpp_frame_get_height(frame);
uint32_t hstride = mpp_frame_get_hor_stride(frame);
uint32_t vstride = mpp_frame_get_ver_stride(frame);
MppFrameFormat format = mpp_frame_get_fmt(frame);
if (mpp_frame_get_info_change(frame)) {
- c2_info("info-change with old dimensions(%dx%d) stride(%dx%d) fmt %d", \
+ c2_info("info-change with old dimensions(%dx%d) stride(%dx%d) fmt %d",
mWidth, mHeight, mHorStride, mVerStride, mColorFormat);
- c2_info("info-change with new dimensions(%dx%d) stride(%dx%d) fmt %d", \
+ c2_info("info-change with new dimensions(%dx%d) stride(%dx%d) fmt %d",
width, height, hstride, vstride, format);
if (!mBufferMode) {
@@ -1091,13 +1167,14 @@
ret = C2_NO_MEMORY;
} else {
- uint32_t err = mpp_frame_get_errinfo(frame);
- int64_t pts = mpp_frame_get_pts(frame);
- uint32_t eos = mpp_frame_get_eos(frame);
+ uint32_t err = mpp_frame_get_errinfo(frame);
+ int64_t pts = mpp_frame_get_pts(frame);
+ uint32_t eos = mpp_frame_get_eos(frame);
uint32_t mode = mpp_frame_get_mode(frame);
MppBuffer mppBuffer = mpp_frame_get_buffer(frame);
- bool isI4O2 = (mode & MPP_FRAME_FLAG_IEP_DEI_MASK) == MPP_FRAME_FLAG_IEP_DEI_I4O2;
+ bool isI4O2 =
+ (mode & MPP_FRAME_FLAG_IEP_DEI_MASK) == MPP_FRAME_FLAG_IEP_DEI_I4O2;
c2_trace("get one frame [%d:%d] stride [%d:%d] pts %lld err %d eos %d",
width, height, hstride, vstride, pts, err, eos);
@@ -1105,6 +1182,7 @@
if (eos) {
c2_info("get output eos.");
mOutputEos = true;
+ isEos = 1;
// ignore null frame with eos
if (!mppBuffer) goto exit;
}
@@ -1119,8 +1197,10 @@
auto c2Handle = mOutBlock->handle();
int32_t dstFd = c2Handle->data[0];
- C2RKRgaDef::paramInit(&src, srcFd, width, height, hstride, vstride);
- C2RKRgaDef::paramInit(&dst, dstFd, width, height, hstride, vstride);
+ C2RKRgaDef::paramInit(&src, srcFd, width, height, hstride,
+ vstride);
+ C2RKRgaDef::paramInit(&dst, dstFd, width, height, hstride,
+ vstride);
if (!C2RKRgaDef::nv12Copy(src, dst)) {
c2_err("faild to copy output to dstBlock on buffer mode.");
ret = C2_CORRUPTED;
@@ -1129,7 +1209,7 @@
} else {
C2GraphicView wView = mOutBlock->map().get();
uint8_t *dst = wView.data()[C2PlanarLayout::PLANE_Y];
- uint8_t *src = (uint8_t*)mpp_buffer_get_ptr(mppBuffer);
+ uint8_t *src = (uint8_t *)mpp_buffer_get_ptr(mppBuffer);
memcpy(dst, src, hstride * vstride * 3 / 2);
}
@@ -1150,16 +1230,16 @@
if (mCodingType == MPP_VIDEO_CodingAVC ||
mCodingType == MPP_VIDEO_CodingHEVC ||
- mCodingType == MPP_VIDEO_CodingMPEG2)
- {
+ mCodingType == MPP_VIDEO_CodingMPEG2) {
getVuiParams(frame);
}
// find frameIndex from pts map.
- for (auto it = mWorkQueue.begin(); it != mWorkQueue.end(); it++) {
+ for (auto it = mMpiDecWorkQueue.begin(); it != mMpiDecWorkQueue.end();
+ it++) {
if (pts == it->second) {
outIndex = it->first;
- mWorkQueue.erase(it);
+ mMpiDecWorkQueue.erase(it);
break;
}
}
@@ -1188,11 +1268,16 @@
entry->outblock = outblock;
entry->frameIndex = outIndex;
-
+ c2_info("entry->frameIndex %d ", entry->frameIndex);
+ if (isEos) {
+ entry->frameIndex = mEosFrameIndex;
+ c2_info("get output eos entry->frameIndex %d ", entry->frameIndex);
+ }
return ret;
}
-c2_status_t C2RKMpiDec::commitBufferToMpp(std::shared_ptr<C2GraphicBlock> block) {
+c2_status_t C2RKMpiDec::commitBufferToMpp(
+ std::shared_ptr<C2GraphicBlock> block) {
if (!block.get()) {
c2_err_f("failed to get block");
return C2_CORRUPTED;
@@ -1204,20 +1289,19 @@
uint32_t bqSlot, width, height, format, stride, generation;
uint64_t usage, bqId;
- android::_UnwrapNativeCodec2GrallocMetadata(
- c2Handle, &width, &height, &format, &usage,
- &stride, &generation, &bqId, &bqSlot);
+ android::_UnwrapNativeCodec2GrallocMetadata(c2Handle, &width, &height,
+ &format, &usage, &stride,
+ &generation, &bqId, &bqSlot);
- auto GetC2BlockSize
- = [c2Handle, width, height, format, usage, stride]() -> uint32_t {
+ auto GetC2BlockSize = [c2Handle, width, height, format, usage,
+ stride]() -> uint32_t {
gralloc_private_handle_t pHandle;
buffer_handle_t bHandle;
native_handle_t *nHandle = UnwrapNativeCodec2GrallocHandle(c2Handle);
GraphicBufferMapper &gm(GraphicBufferMapper::get());
- gm.importBuffer(const_cast<native_handle_t *>(nHandle),
- width, height, 1, format, usage,
- stride, &bHandle);
+ gm.importBuffer(const_cast<native_handle_t *>(nHandle), width, height,
+ 1, format, usage, stride, &bHandle);
Rockchip_get_gralloc_private((uint32_t *)bHandle, &pHandle);
@@ -1237,7 +1321,8 @@
buffer->block = block;
buffer->site = BUFFER_SITE_BY_MPI;
- c2_trace("put this buffer: slot %d fd %d buf %p", bqSlot, fd, mppBuffer);
+ c2_trace("put this buffer: slot %d fd %d buf %p", bqSlot, fd,
+ mppBuffer);
} else {
/* register this buffer to mpp group */
MppBuffer mppBuffer;
@@ -1250,8 +1335,8 @@
info.hnd = nullptr;
info.size = GetC2BlockSize();
- mpp_buffer_import_with_tag(mFrmGrp, &info,
- &mppBuffer, "codec2", __FUNCTION__);
+ mpp_buffer_import_with_tag(mFrmGrp, &info, &mppBuffer, "codec2",
+ __FUNCTION__);
OutBuffer *buffer = new OutBuffer;
buffer->index = bqSlot;
@@ -1262,22 +1347,23 @@
mOutBuffers.push(buffer);
- c2_trace("import this buffer: slot %d fd %d size %d buf %p", bqSlot,
- fd, info.size, mppBuffer);
+ c2_trace("import this buffer: slot %d fd %d size %d buf %p", bqSlot, fd,
+ info.size, mppBuffer);
}
return C2_OK;
}
c2_status_t C2RKMpiDec::ensureDecoderState(
- const std::shared_ptr<C2BlockPool> &pool) {
+ const std::shared_ptr<C2BlockPool> &pool) {
c2_status_t ret = C2_OK;
uint32_t blockW = mHorStride;
uint32_t blockH = mVerStride;
- uint64_t usage = RK_GRALLOC_USAGE_SPECIFY_STRIDE;
- uint32_t format = C2RKMediaUtils::colorFormatMpiToAndroid(mColorFormat, mFbcCfg.mode);
+ uint64_t usage = RK_GRALLOC_USAGE_SPECIFY_STRIDE;
+ uint32_t format =
+ C2RKMediaUtils::colorFormatMpiToAndroid(mColorFormat, mFbcCfg.mode);
// workround for tencent-video, the application can not deal with crop
// correctly, so use actual dimention when fetch block, make sure that
@@ -1299,12 +1385,14 @@
}
}
- switch(mTransfer) {
+ switch (mTransfer) {
case ColorTransfer::kColorTransferST2084:
- usage |= ((GRALLOC_NV12_10_HDR_10 << 24) & GRALLOC_COLOR_SPACE_MASK); // hdr10;
+ usage |= ((GRALLOC_NV12_10_HDR_10 << 24) &
+ GRALLOC_COLOR_SPACE_MASK); // hdr10;
break;
case ColorTransfer::kColorTransferHLG:
- usage |= ((GRALLOC_NV12_10_HDR_HLG << 24) & GRALLOC_COLOR_SPACE_MASK); // hdr-hlg
+ usage |= ((GRALLOC_NV12_10_HDR_HLG << 24) &
+ GRALLOC_COLOR_SPACE_MASK); // hdr-hlg
break;
}
@@ -1315,13 +1403,13 @@
*/
if (mBufferMode) {
if (mOutBlock &&
- (mOutBlock->width() != blockW || mOutBlock->height() != blockH)) {
+ (mOutBlock->width() != blockW || mOutBlock->height() != blockH)) {
mOutBlock.reset();
}
if (!mOutBlock) {
- ret = pool->fetchGraphicBlock(blockW, blockH, format,
- C2AndroidMemoryUsage::FromGrallocUsage(usage),
- &mOutBlock);
+ ret = pool->fetchGraphicBlock(
+ blockW, blockH, format,
+ C2AndroidMemoryUsage::FromGrallocUsage(usage), &mOutBlock);
if (ret != C2_OK) {
c2_err("failed to fetchGraphicBlock, err %d", ret);
return ret;
@@ -1335,9 +1423,9 @@
uint32_t i = 0;
for (i = 0; i < count; i++) {
- ret = pool->fetchGraphicBlock(blockW, blockH, format,
- C2AndroidMemoryUsage::FromGrallocUsage(usage),
- &outblock);
+ ret = pool->fetchGraphicBlock(
+ blockW, blockH, format,
+ C2AndroidMemoryUsage::FromGrallocUsage(usage), &outblock);
if (ret != C2_OK) {
c2_err("failed to fetchGraphicBlock, err %d", ret);
break;
@@ -1357,55 +1445,54 @@
}
class C2RKMpiDecFactory : public C2ComponentFactory {
-public:
+ public:
C2RKMpiDecFactory(std::string componentName)
- : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
- GetCodec2PlatformComponentStore()->getParamReflector())),
- mComponentName(componentName) {
+ : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
+ GetCodec2PlatformComponentStore()->getParamReflector())),
+ mComponentName(componentName) {
if (!C2RKMediaUtils::getMimeFromComponentName(componentName, &mMime)) {
- c2_err("failed to get mime from component %s", componentName.c_str());
+ c2_err("failed to get mime from component %s",
+ componentName.c_str());
}
- if (!C2RKMediaUtils::getDomainFromComponentName(componentName, &mDomain)) {
- c2_err("failed to get domain from component %s", componentName.c_str());
+ if (!C2RKMediaUtils::getDomainFromComponentName(componentName,
+ &mDomain)) {
+ c2_err("failed to get domain from component %s",
+ componentName.c_str());
}
if (!C2RKMediaUtils::getKindFromComponentName(componentName, &mKind)) {
- c2_err("failed to get kind from component %s", componentName.c_str());
+ c2_err("failed to get kind from component %s",
+ componentName.c_str());
}
}
virtual c2_status_t createComponent(
- c2_node_id_t id,
- std::shared_ptr<C2Component>* const component,
- std::function<void(C2Component*)> deleter) override {
+ c2_node_id_t id, std::shared_ptr<C2Component> *const component,
+ std::function<void(C2Component *)> deleter) override {
c2_trace_f("in");
*component = std::shared_ptr<C2Component>(
- new C2RKMpiDec(
- mComponentName.c_str(),
- id,
- std::make_shared<C2RKMpiDec::IntfImpl>
- (mHelper, mComponentName, mKind, mDomain, mMime)),
- deleter);
+ new C2RKMpiDec(mComponentName.c_str(), id,
+ std::make_shared<C2RKMpiDec::IntfImpl>(
+ mHelper, mComponentName, mKind, mDomain, mMime)),
+ deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(C2ComponentInterface*)> deleter) override {
+ c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *const interface,
+ std::function<void(C2ComponentInterface *)> deleter) override {
c2_trace_f("in");
*interface = std::shared_ptr<C2ComponentInterface>(
- new C2RKInterface<C2RKMpiDec::IntfImpl>(
- mComponentName.c_str(),
- id,
- std::make_shared<C2RKMpiDec::IntfImpl>
- (mHelper, mComponentName, mKind, mDomain, mMime)),
- deleter);
+ new C2RKInterface<C2RKMpiDec::IntfImpl>(
+ mComponentName.c_str(), id,
+ std::make_shared<C2RKMpiDec::IntfImpl>(mHelper, mComponentName,
+ mKind, mDomain, mMime)),
+ deleter);
return C2_OK;
}
virtual ~C2RKMpiDecFactory() override = default;
-private:
+ private:
std::shared_ptr<C2ReflectorHelper> mHelper;
std::string mComponentName;
std::string mMime;
@@ -1413,7 +1500,7 @@
C2Component::domain_t mDomain;
};
-C2ComponentFactory* CreateRKMpiDecFactory(std::string componentName) {
+C2ComponentFactory *CreateRKMpiDecFactory(std::string componentName) {
c2_trace_f("in");
return new ::android::C2RKMpiDecFactory(componentName);
}
diff --git a/component/mpi/C2RKMpiEnc.cpp b/component/mpi/C2RKMpiEnc.cpp
index 399a7f8..158ddc3 100755
--- a/component/mpi/C2RKMpiEnc.cpp
+++ b/component/mpi/C2RKMpiEnc.cpp
@@ -696,6 +696,7 @@
mVerStride(0),
mInFile(nullptr),
mOutFile(nullptr) {
+ isEncoder = true;
c2_info("version: %s", C2_GIT_BUILD_VERSION);
if (!C2RKMediaUtils::getCodingTypeFromComponentName(name, &mCodingType)) {
@@ -1718,6 +1719,185 @@
}
}
+
+void C2RKMpiEnc::inputPart(
+ std::unique_ptr<C2Work> &work,
+ const std::shared_ptr<C2BlockPool> &pool) {
+ c2_status_t err = C2_OK;
+
+ // Initialize output work
+ work->result = C2_OK;
+ work->workletsProcessed = 0u;
+ work->worklets.front()->output.flags = work->input.flags;
+
+ // Initialize encoder if not already initialized
+ if (!mStarted) {
+
+ err = initEncoder();
+ if (err != C2_OK) {
+ work->result = C2_BAD_VALUE;
+ c2_info("failed to initialize, signalled Error");
+ return;
+ }
+ if (mThreadEnabled.exchange(false)) {
+ c2_status_t result = C2_OK;
+
+ c2_info_f("mOutFrameThread.stop");
+ result = mOutFrameThread.stop();
+ }
+ }
+
+ if (mSignalledError) {
+ work->result = C2_BAD_VALUE;
+ c2_info("Signalled Error");
+ return;
+ }
+
+ std::shared_ptr<const C2GraphicView> view;
+ std::shared_ptr<C2Buffer> inputBuffer = nullptr;
+ if (!work->input.buffers.empty()) {
+ inputBuffer = work->input.buffers[0];
+ view = std::make_shared<const C2GraphicView>(
+ inputBuffer->data().graphicBlocks().front().map().get());
+ if (view->error() != C2_OK) {
+ c2_err("graphic view map err = %d", view->error());
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ return;
+ }
+ const C2GraphicView *const input = view.get();
+ if ((input != nullptr) && (input->width() < mSize->width ||
+ input->height() < mSize->height)) {
+ /* Expect width height to be configured */
+ c2_err("unexpected Capacity Aspect %d(%d) x %d(%d)",
+ input->width(), mSize->width, input->height(), mSize->height);
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ return;
+ }
+ }
+
+ uint32_t flags = work->input.flags;
+ uint64_t frameIndex = work->input.ordinal.frameIndex.peekull();
+ uint64_t timestamp = work->input.ordinal.timestamp.peekll();
+
+ c2_trace("process one work timestamp %llu frameindex %llu, flags %x",
+ timestamp, frameIndex, flags);
+
+ mSawInputEOS = (flags & C2FrameData::FLAG_END_OF_STREAM);
+
+ if (!mSpsPpsHeaderReceived) {
+ MppPacket hdrPkt = nullptr;
+ void *hdrBuf = nullptr;
+ void *extradata = nullptr;
+ uint32_t hdrBufSize = 1024;
+ uint32_t extradataSize = 0;
+
+ hdrBuf = malloc(hdrBufSize * sizeof(uint8_t));
+ if (hdrBuf)
+ mpp_packet_init(&hdrPkt, hdrBuf, hdrBufSize);
+
+ if (hdrPkt) {
+ mMppMpi->control(mMppCtx, MPP_ENC_GET_HDR_SYNC, hdrPkt);
+ extradataSize = mpp_packet_get_length(hdrPkt);
+ extradata = mpp_packet_get_data(hdrPkt);
+ }
+
+ std::unique_ptr<C2StreamInitDataInfo::output> csd =
+ C2StreamInitDataInfo::output::AllocUnique(extradataSize, 0u);
+ if (!csd) {
+ c2_err("CSD allocation failed");
+ work->result = C2_NO_MEMORY;
+ work->workletsProcessed = 1u;
+ C2_SAFE_FREE(hdrBuf);
+ return;
+ }
+
+ memcpy(csd->m.value, extradata, extradataSize);
+ work->worklets.front()->output.configUpdate.push_back(std::move(csd));
+
+ if (mOutFile != nullptr) {
+ fwrite(extradata, 1, extradataSize , mOutFile);
+ fflush(mOutFile);
+ }
+
+ mSpsPpsHeaderReceived = true;
+
+ if (hdrPkt){
+ mpp_packet_deinit(&hdrPkt);
+ hdrPkt = NULL;
+ }
+ C2_SAFE_FREE(hdrBuf);
+
+ if (work->input.buffers.empty()) {
+ work->workletsProcessed = 1u;
+ return;
+ }
+ }
+
+ {
+ // handle dynamic config parameters
+ // TODO set bitrate dynamically
+ IntfImpl::Lock lock = mIntf->lock();
+ std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l();
+ lock.unlock();
+ if (bitrate != mBitrate) {
+ c2_info("new bitrate requeset, value %d", bitrate->value);
+ mBitrate = bitrate;
+ }
+ }
+
+ MyDmaBuffer_t inDmaBuf;
+ OutWorkEntry entry;
+
+ memset(&inDmaBuf, 0, sizeof(MyDmaBuffer_t));
+ memset(&entry, 0, sizeof(OutWorkEntry));
+
+ err = getInBufferFromWork(work, &inDmaBuf);
+ if (err != C2_OK) {
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ return;
+ }
+
+ /* send frame to mpp */
+ err = sendframe(inDmaBuf, frameIndex, flags);
+ if (C2_OK != err) {
+ c2_err("failed to enqueue frame, err %d", err);
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ return;
+ }
+
+ /* get packet from mpp */
+ err = getoutpacket(&entry);
+ if (err == C2_OK) {
+ finishWork(work, pool, entry);
+ } else {
+ if (work && work->workletsProcessed != 1u) {
+ fillEmptyWork(work);
+ }
+ }
+
+ if (!mSawInputEOS && work->input.buffers.empty()) {
+ fillEmptyWork(work);
+ }
+
+ if (mSawInputEOS && !mOutputEOS) {
+ drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
+ }
+
+}
+
+
+void C2RKMpiEnc::outputPart(const std::shared_ptr<C2BlockPool> &pool) {
+ (void) pool;
+}
+
c2_status_t C2RKMpiEnc::getInBufferFromWork(
const std::unique_ptr<C2Work> &work, MyDmaBuffer_t *outBuffer) {
c2_status_t ret = C2_OK;
diff --git a/services/C2RKComponentStore.cpp b/services/C2RKComponentStore.cpp
index 264d1bf..9822be9 100755
--- a/services/C2RKComponentStore.cpp
+++ b/services/C2RKComponentStore.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#define LOG_NDEBUG 0
#undef ROCKCHIP_LOG_TAG
#define ROCKCHIP_LOG_TAG "C2RKComponentStore"