Merge "codec2: MTS add new tests for video dec" into pi-dev
diff --git a/codec2/hidl/client/client.cpp b/codec2/hidl/client/client.cpp
index 48a9d5d..9a82712 100644
--- a/codec2/hidl/client/client.cpp
+++ b/codec2/hidl/client/client.cpp
@@ -825,7 +825,12 @@
     std::vector<uint64_t> inputDone;
     for (const std::unique_ptr<C2Work> &work : workItems) {
         if (work) {
-            inputDone.emplace_back(work->input.ordinal.frameIndex.peeku());
+            if (work->worklets.empty()
+                    || !work->worklets.back()
+                    || (work->worklets.back()->output.flags & C2FrameData::FLAG_INCOMPLETE) == 0) {
+                // input is complete
+                inputDone.emplace_back(work->input.ordinal.frameIndex.peeku());
+            }
         }
     }
 
diff --git a/codec2/include/C2Work.h b/codec2/include/C2Work.h
index 2d3e71c..6923f3e 100644
--- a/codec2/include/C2Work.h
+++ b/codec2/include/C2Work.h
@@ -132,6 +132,19 @@
          */
         FLAG_DISCARD_FRAME = (1 << 2),
         /**
+         * This frame is not the last frame produced for the input.
+         *
+         * This flag is normally set by the component - e.g. when an input frame results in multiple
+         * output frames, this flag is set on all but the last output frame.
+         *
+         * Also, when components are chained, this flag should be propagated down the
+         * work chain. That is, if set on an earlier frame of a work-chain, it should be propagated
+         * to all later frames in that chain. Additionally, components down the chain could set
+         * this flag even if not set earlier, e.g. if multiple output frame is generated at that
+         * component for the input frame.
+         */
+        FLAG_INCOMPLETE = (1 << 3),
+        /**
          * This frame contains only codec-specific configuration data, and no actual access unit.
          *
          * \deprecated pass codec configuration with using the \todo codec-specific configuration
diff --git a/media/sfplugin/CCodec.cpp b/media/sfplugin/CCodec.cpp
index 066e4f1..75c6b0c 100644
--- a/media/sfplugin/CCodec.cpp
+++ b/media/sfplugin/CCodec.cpp
@@ -1392,7 +1392,7 @@
     switch (msg->what()) {
         case kWhatAllocate: {
             // C2ComponentStore::createComponent() should return within 100ms.
-            setDeadline(now + 150ms, "allocate");
+            setDeadline(now, 150ms, "allocate");
             sp<RefBase> obj;
             CHECK(msg->findObject("codecInfo", &obj));
             allocate((MediaCodecInfo *)obj.get());
@@ -1400,7 +1400,7 @@
         }
         case kWhatConfigure: {
             // C2Component::commit_sm() should return within 5ms.
-            setDeadline(now + 50ms, "configure");
+            setDeadline(now, 50ms, "configure");
             sp<AMessage> format;
             CHECK(msg->findMessage("format", &format));
             configure(format);
@@ -1408,14 +1408,14 @@
         }
         case kWhatStart: {
             // C2Component::start() should return within 500ms.
-            setDeadline(now + 550ms, "start");
+            setDeadline(now, 550ms, "start");
             mQueuedWorkCount = 0;
             start();
             break;
         }
         case kWhatStop: {
             // C2Component::stop() should return within 500ms.
-            setDeadline(now + 550ms, "stop");
+            setDeadline(now, 550ms, "stop");
             stop();
 
             mQueuedWorkCount = 0;
@@ -1425,19 +1425,19 @@
         }
         case kWhatFlush: {
             // C2Component::flush_sm() should return within 5ms.
-            setDeadline(now + 50ms, "flush");
+            setDeadline(now, 50ms, "flush");
             flush();
             break;
         }
         case kWhatCreateInputSurface: {
             // Surface operations may be briefly blocking.
-            setDeadline(now + 100ms, "createInputSurface");
+            setDeadline(now, 100ms, "createInputSurface");
             createInputSurface();
             break;
         }
         case kWhatSetInputSurface: {
             // Surface operations may be briefly blocking.
-            setDeadline(now + 100ms, "setInputSurface");
+            setDeadline(now, 100ms, "setInputSurface");
             sp<RefBase> obj;
             CHECK(msg->findObject("surface", &obj));
             sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
@@ -1445,7 +1445,7 @@
             break;
         }
         case kWhatSetParameters: {
-            setDeadline(now + 50ms, "setParameters");
+            setDeadline(now, 50ms, "setParameters");
             sp<AMessage> params;
             CHECK(msg->findMessage("params", &params));
             setParameters(params);
@@ -1542,12 +1542,16 @@
             break;
         }
     }
-    setDeadline(TimePoint::max(), "none");
+    setDeadline(TimePoint::max(), 0ms, "none");
 }
 
-void CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
+void CCodec::setDeadline(
+        const TimePoint &now,
+        const std::chrono::milliseconds &timeout,
+        const char *name) {
+    int32_t mult = std::max(1, property_get_int32("debug.stagefright.ccodec_timeout_mult", 1));
     Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
-    deadline->set(newDeadline, name);
+    deadline->set(now + (timeout * mult), name);
 }
 
 void CCodec::initiateReleaseIfStuck() {
diff --git a/media/sfplugin/CCodec.h b/media/sfplugin/CCodec.h
index a5f28da..252ccef 100644
--- a/media/sfplugin/CCodec.h
+++ b/media/sfplugin/CCodec.h
@@ -93,7 +93,10 @@
     status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
     void setParameters(const sp<AMessage> &params);
 
-    void setDeadline(const TimePoint &deadline, const char *name);
+    void setDeadline(
+            const TimePoint &now,
+            const std::chrono::milliseconds &timeout,
+            const char *name);
 
     void onWorkQueued(bool eos);
     void subQueuedWorkCount(uint32_t count);