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