From 8877ce273f63048b1e78d1453bb87da34f6937ec Mon Sep 17 00:00:00 2001
From: kkostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Wed, 24 Feb 2021 11:26:38 -0500
Subject: [PATCH] video: improve CPU usage on decoding

When frame decoding is fast, av_read_frame called before new data
available. It will cause high CPU usage.
This patch adds wait time when no data is available.

Change-Id: I675092e2497f969976f797cc1bbb6b466b9dbcb5
---
 src/media/media_decoder.cpp | 15 +++++++++++++++
 src/media/media_decoder.h   |  1 +
 2 files changed, 16 insertions(+)

diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index 18f287e97a..894f4bde6d 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -325,6 +325,19 @@ MediaDemuxer::decode()
 
     int ret = av_read_frame(inputCtx_, packet.get());
     if (ret == AVERROR(EAGAIN)) {
+        /*no data available. Calculate time until next frame.
+         We do not use the emulated frame mechanism from the decoder because it will affect all platforms.
+         With the current implementation, the demuxer will be waiting just in case when av_read_frame
+         returns EAGAIN. For some platforms, av_read_frame is blocking and it will never happen.
+         */
+        if (inputParams_.framerate.numerator() == 0)
+            return Status::Success;
+        rational<double> frameTime = 1e6/inputParams_.framerate;
+        int64_t timeToSleep = lastReadPacketTime_ - av_gettime_relative() + frameTime.real<int64_t>();
+        if (timeToSleep <= 0) {
+            return Status::Success;
+        }
+        std::this_thread::sleep_for(std::chrono::microseconds(timeToSleep));
         return Status::Success;
     } else if (ret == AVERROR_EOF) {
         return Status::EndOfFile;
@@ -338,6 +351,8 @@ MediaDemuxer::decode()
         return Status::Success;
     }
 
+    lastReadPacketTime_ = av_gettime_relative();
+
     auto& cb = streams_[streamIndex];
     if (cb) {
         DecodeStatus ret = cb(*packet.get());
diff --git a/src/media/media_decoder.h b/src/media/media_decoder.h
index 917e54ab7a..826a9ab10b 100644
--- a/src/media/media_decoder.h
+++ b/src/media/media_decoder.h
@@ -131,6 +131,7 @@ private:
     AVFormatContext* inputCtx_ = nullptr;
     std::vector<StreamCallback> streams_;
     int64_t startTime_;
+    int64_t lastReadPacketTime_ {};
     DeviceParams inputParams_;
     AVDictionary* options_ = nullptr;
     MediaDemuxer::CurrentState currentState_;
-- 
GitLab