Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qffmpegtimecontroller.cpp
Go to the documentation of this file.
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
4#include "playbackengine/qffmpegtimecontroller_p.h"
5
6#include "qglobal.h"
7#include "qdebug.h"
8
9#include <algorithm>
10
11QT_BEGIN_NAMESPACE
12
13namespace QFFmpeg {
14
16{
17 sync();
18}
19
21{
22 return m_playbackRate;
23}
24
26{
27 if (playbackRate == m_playbackRate)
28 return;
29
30 Q_ASSERT(playbackRate > 0.f);
31
32 scrollTimeTillNow();
33 m_playbackRate = playbackRate;
34
35 if (m_softSyncData)
36 m_softSyncData = makeSoftSyncData(m_timePoint, m_position, m_softSyncData->dstTimePoint);
37}
38
39void TimeController::sync(TrackPosition trackPos)
40{
41 sync(SteadyClock::now(), trackPos);
42}
43
44void TimeController::sync(TimePoint tp, TrackPosition pos)
45{
46 m_softSyncData.reset();
47 m_position = pos;
48 m_timePoint = tp;
49}
50
51void TimeController::syncSoft(TimePoint tp, TrackPosition pos, SteadyClock::duration fixingTime)
52{
53 const auto srcTime = SteadyClock::now();
54 const auto srcPos = positionFromTime(srcTime, true);
55 const auto dstTime = srcTime + fixingTime;
56
57 m_position = pos;
58 m_timePoint = tp;
59
60 m_softSyncData = makeSoftSyncData(srcTime, srcPos, dstTime);
61}
62
63TrackPosition TimeController::currentPosition(SteadyClock::duration offset) const
64{
65 return positionFromTime(SteadyClock::now() + offset);
66}
68{
69 m_started = true;
70 updateActive();
71}
72
74{
75 m_started = false;
76 m_paused = true;
77 updateActive();
78}
79
80void TimeController::setPaused(bool paused)
81{
82 m_paused = paused;
83 updateActive();
84}
85
86void TimeController::updateActive()
87{
88 const bool active = !m_paused && m_started;
89 if (m_active == active)
90 return;
91
92 scrollTimeTillNow();
93
94 m_active = active;
95}
96
97TrackPosition TimeController::positionFromTime(TimePoint tp, bool ignoreInactive) const
98{
99 tp = !m_active && !ignoreInactive ? m_timePoint : tp;
100
101 if (m_softSyncData && tp < m_softSyncData->dstTimePoint) {
102 const PlaybackRate rate =
103 tp > m_softSyncData->srcTimePoint ? m_softSyncData->internalRate : m_playbackRate;
104
105 return m_softSyncData->srcPosition
106 + toTrackDuration(tp - m_softSyncData->srcTimePoint, rate);
107 }
108
109 return positionFromTimeInternal(tp);
110}
111
113 bool ignoreInactive) const
114{
115 auto position = !m_active && !ignoreInactive ? m_position : TrackPosition(pos);
116
117 if (m_softSyncData && position < m_softSyncData->dstPosition) {
118 const auto rate = position > m_softSyncData->srcPosition ? m_softSyncData->internalRate
119 : m_playbackRate;
120 return m_softSyncData->srcTimePoint
121 + toClockDuration(position - m_softSyncData->srcPosition, rate);
122 }
123
124 return timeFromPositionInternal(position);
125}
126
127TimeController::SoftSyncData TimeController::makeSoftSyncData(const TimePoint &srcTp,
128 const TrackPosition &srcPos,
129 const TimePoint &dstTp) const
130{
131 SoftSyncData result;
132 result.srcTimePoint = srcTp;
133 result.srcPosition = srcPos;
134 result.dstTimePoint = dstTp;
135 result.srcPosOffest = srcPos - positionFromTimeInternal(srcTp);
136 result.dstPosition = positionFromTimeInternal(dstTp);
137 result.internalRate =
138 static_cast<PlaybackRate>(toClockDuration(result.dstPosition - srcPos).count())
139 / (dstTp - srcTp).count();
140
141 return result;
142}
143
144TrackPosition TimeController::positionFromTimeInternal(const TimePoint &tp) const
145{
146 return m_position + toTrackDuration(tp - m_timePoint, m_playbackRate);
147}
148
149TimeController::TimePoint TimeController::timeFromPositionInternal(const TrackPosition &pos) const
150{
151 return m_timePoint + toClockDuration(pos - m_position, m_playbackRate);
152}
153
154void TimeController::scrollTimeTillNow()
155{
156 const auto now = SteadyClock::now();
157 if (m_active) {
158 m_position = positionFromTimeInternal(now);
159
160 // let's forget outdated syncronizations
161 if (m_softSyncData && m_softSyncData->dstTimePoint <= now)
162 m_softSyncData.reset();
163 } else if (m_softSyncData) {
164 m_softSyncData->dstTimePoint += now - m_timePoint;
165 m_softSyncData->srcTimePoint += now - m_timePoint;
166 }
167
168 m_timePoint = now;
169}
170
171SteadyClock::duration TimeController::toClockDuration(TrackDuration trackDuration, PlaybackRate rate)
172{
173 return std::chrono::duration_cast<SteadyClock::duration>(
174 std::chrono::microseconds(trackDuration.get()) / rate);
175}
176
177TrackDuration TimeController::toTrackDuration(SteadyClock::duration clockDuration, PlaybackRate rate)
178{
179 return TrackDuration(
180 std::chrono::duration_cast<std::chrono::microseconds>(clockDuration * rate).count());
181}
182
183} // namespace QFFmpeg
184
185QT_END_NAMESPACE
void syncSoft(TimePoint tp, TrackPosition pos, SteadyClock::duration fixingTime=std::chrono::seconds(4))
PlaybackRate playbackRate() const
TrackPosition currentPosition(SteadyClock::duration offset=SteadyClock::duration{ 0 }) const
TimePoint timeFromPosition(TrackPosition pos, bool ignoreInactive=false) const
TrackPosition positionFromTime(TimePoint tp, bool ignoreInactive=false) const
void sync(TimePoint tp, TrackPosition pos)
void setPlaybackRate(PlaybackRate playbackRate)
void sync(TrackPosition trackPos=TrackPosition(0))
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType