From df46a50615136adeac39223953ab7aed393ebd08 Mon Sep 17 00:00:00 2001 From: Artem Dyomin Date: Thu, 11 May 2023 13:38:56 +0200 Subject: Improve getting ffmpeg frame duration FFmpeg doc says that AVFrame.duration represents the duration except cases if it's 0 (unknown). It's appeared in only 6.0 so we use a helper to get it. So let's apply the rule to our AVFrame wrapper. Pick-to: 6.5 Change-Id: I9596364561f88929796c0097381bfc26bf1d4565 Reviewed-by: Qt CI Bot Reviewed-by: Lars Knoll --- .../multimedia/ffmpeg/playbackengine/qffmpegframe_p.h | 11 +++++++---- src/plugins/multimedia/ffmpeg/qffmpeg_p.h | 13 ++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegframe_p.h b/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegframe_p.h index 459ceb9b4..e84e0e191 100644 --- a/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegframe_p.h +++ b/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegframe_p.h @@ -41,10 +41,13 @@ struct Frame pts = codec.toUs(frame->pts); else pts = codec.toUs(frame->best_effort_timestamp); - const auto &avgFrameRate = codec.stream()->avg_frame_rate; - duration = avgFrameRate.num - ? (1000000 * avgFrameRate.den + avgFrameRate.num / 2) / avgFrameRate.num - : 0; + + if (auto frameDuration = getAVFrameDuration(*frame)) { + duration = codec.toUs(frameDuration); + } else { + const auto &avgFrameRate = codec.stream()->avg_frame_rate; + duration = mul(qint64(1000000), { avgFrameRate.den, avgFrameRate.num }).value_or(0); + } } Data(const LoopOffset &offset, const QString &text, qint64 pts, qint64 duration, const QObject *source) diff --git a/src/plugins/multimedia/ffmpeg/qffmpeg_p.h b/src/plugins/multimedia/ffmpeg/qffmpeg_p.h index 44fd66cf2..ec927f8b5 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpeg_p.h +++ b/src/plugins/multimedia/ffmpeg/qffmpeg_p.h @@ -20,6 +20,8 @@ extern "C" { (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 91, 100)) // since ffmpeg n4.3 #define QT_FFMPEG_HAS_FRAME_TIME_BASE \ (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59, 18, 100)) // since ffmpeg n5.0 +#define QT_FFMPEG_HAS_FRAME_DURATION \ + (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 3, 100)) // since ffmpeg n6.0 QT_BEGIN_NAMESPACE @@ -68,7 +70,7 @@ inline void setAVFrameTime(AVFrame &frame, int64_t pts, const AVRational &timeBa #endif } -inline void getAVFrameTime(AVFrame &frame, int64_t &pts, AVRational &timeBase) +inline void getAVFrameTime(const AVFrame &frame, int64_t &pts, AVRational &timeBase) { pts = frame.pts; #if QT_FFMPEG_HAS_FRAME_TIME_BASE @@ -78,6 +80,15 @@ inline void getAVFrameTime(AVFrame &frame, int64_t &pts, AVRational &timeBase) #endif } +inline int64_t getAVFrameDuration(const AVFrame &frame) +{ +#if QT_FFMPEG_HAS_FRAME_DURATION + return frame.duration; +#else + return 0; +#endif +} + struct AVDictionaryHolder { AVDictionary *opts = nullptr; -- cgit v1.2.1