1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QFFMPEGRENDERER_P_H
4#define QFFMPEGRENDERER_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include "playbackengine/qffmpegplaybackengineobject_p.h"
18#include "playbackengine/qffmpegtimecontroller_p.h"
19#include "playbackengine/qffmpegframe_p.h"
20
21#include <QtCore/qpointer.h>
22
23#include <chrono>
24
25QT_BEGIN_NAMESPACE
26
27namespace QFFmpeg {
28
29class Renderer : public PlaybackEngineObject
30{
31 Q_OBJECT
32public:
33 using TimePoint = TimeController::TimePoint;
34 using Clock = TimeController::Clock;
35 Renderer(const TimeController &tc, const std::chrono::microseconds &seekPosTimeOffset = {});
36
37 void syncSoft(TimePoint tp, qint64 trackPos);
38
39 qint64 seekPosition() const;
40
41 qint64 lastPosition() const;
42
43 void setPlaybackRate(float rate);
44
45 void doForceStep();
46
47 bool isStepForced() const;
48
49public slots:
50 void setInitialPosition(TimePoint tp, qint64 trackPos);
51
52 void onFinalFrameReceived();
53
54 void render(Frame);
55
56signals:
57 void frameProcessed(Frame);
58
59 void synchronized(Id id, TimePoint tp, qint64 pos);
60
61 void forceStepDone();
62
63 void loopChanged(Id id, qint64 offset, int index);
64
65protected:
66 bool setForceStepDone();
67
68 void onPauseChanged() override;
69
70 bool canDoNextStep() const override;
71
72 int timerInterval() const override;
73
74 virtual void onPlaybackRateChanged() { }
75
76 struct RenderingResult
77 {
78 bool done = true;
79 std::chrono::microseconds recheckInterval = std::chrono::microseconds(0);
80 };
81
82 virtual RenderingResult renderInternal(Frame frame) = 0;
83
84 float playbackRate() const;
85
86 std::chrono::microseconds frameDelay(const Frame &frame,
87 TimePoint timePoint = Clock::now()) const;
88
89 void changeRendererTime(std::chrono::microseconds offset);
90
91 template<typename Output, typename ChangeHandler>
92 void setOutputInternal(QPointer<Output> &actual, Output *desired, ChangeHandler &&changeHandler)
93 {
94 const auto connectionType = thread() == QThread::currentThread()
95 ? Qt::AutoConnection
96 : Qt::BlockingQueuedConnection;
97 auto doer = [desired, changeHandler, &actual]() {
98 const auto prev = std::exchange(actual, desired);
99 if (prev != desired)
100 changeHandler(prev);
101 };
102 QMetaObject::invokeMethod(this, doer, connectionType);
103 }
104
105private:
106 void doNextStep() override;
107
108private:
109 TimeController m_timeController;
110 qint64 m_lastFrameEnd = 0;
111 QAtomicInteger<qint64> m_lastPosition = 0;
112 QAtomicInteger<qint64> m_seekPos = 0;
113
114 int m_loopIndex = 0;
115 QQueue<Frame> m_frames;
116
117 QAtomicInteger<bool> m_isStepForced = false;
118 std::optional<TimePoint> m_explicitNextFrameTime;
119};
120
121} // namespace QFFmpeg
122
123QT_END_NAMESPACE
124
125#endif // QFFMPEGRENDERER_P_H
126

source code of qtmultimedia/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegrenderer_p.h