Rockchip Android12 Codec2 插件 多线程实现代码

基于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> &currentWork) {
+    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> &currentWork,
@@ -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> &currentWork);
+
     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"
 

猜你喜欢

转载自blog.csdn.net/hi_zhengjian/article/details/126531857
今日推荐