CCodec: skip first N longest work inside total delay

If the client pauses pushing input to the component, work items inside
total delay may sit in the pipeline indefinitely. We don't want to
error out for those work. Once the client pushes EOS, ensure all work
items finishes within reasonable time regardless of delay.

Bug: 124355114
Test: manual
Test: atest CtsSecurityTestCases:StagefrightTest
Test: atest CtsMediaTestCases -- --module-arg CtsMediaTestCases:size:small
Change-Id: I0e95b2ddb94482da855d70cbe75f6bffaaffe279
diff --git a/media/codec2/sfplugin/PipelineWatcher.cpp b/media/codec2/sfplugin/PipelineWatcher.cpp
index fe0a2c8..cdcc41b 100644
--- a/media/codec2/sfplugin/PipelineWatcher.cpp
+++ b/media/codec2/sfplugin/PipelineWatcher.cpp
@@ -127,19 +127,21 @@
 }
 
 PipelineWatcher::Clock::duration PipelineWatcher::elapsed(
-        const PipelineWatcher::Clock::time_point &now) const {
-    return std::accumulate(
-            mFramesInPipeline.begin(),
-            mFramesInPipeline.end(),
-            Clock::duration::zero(),
-            [&now](const Clock::duration &current,
-                   const decltype(mFramesInPipeline)::value_type &value) {
-                Clock::duration elapsed = now - value.second.queuedAt;
-                ALOGV("elapsed: frameIndex = %llu elapsed = %lldms",
-                      (unsigned long long)value.first,
-                      std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count());
-                return current > elapsed ? current : elapsed;
-            });
+        const PipelineWatcher::Clock::time_point &now, size_t n) const {
+    if (mFramesInPipeline.size() <= n) {
+        return Clock::duration::zero();
+    }
+    std::vector<Clock::duration> durations;
+    for (const decltype(mFramesInPipeline)::value_type &value : mFramesInPipeline) {
+        Clock::duration elapsed = now - value.second.queuedAt;
+        ALOGV("elapsed: frameIndex = %llu elapsed = %lldms",
+              (unsigned long long)value.first,
+              std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count());
+        durations.push_back(elapsed);
+    }
+    nth_element(durations.begin(), durations.end(), durations.begin() + n,
+                std::greater<Clock::duration>());
+    return durations[n];
 }
 
 }  // namespace android