85 const auto isFrameOutdated = frame.isValid() && frame.absoluteEnd() < seekPosition();
87 if (isFrameOutdated) {
88 qCDebug(qLcRenderer) <<
"frame outdated! absEnd:" << frame.absoluteEnd().get() <<
"absPts"
89 << frame.absolutePts().get() <<
"seekPos:" << seekPosition().get();
90 emit frameProcessed(std::move(frame));
94 m_frames.enqueue(std::move(frame));
96 if (m_frames.size() == 1)
124 using namespace std::chrono_literals;
126 if (m_frames.empty())
129 auto calculateInterval = [](
const TimePoint &nextTime) {
130 using namespace std::chrono;
132 const milliseconds delay = duration_cast<milliseconds>(nextTime - SteadyClock::now());
133 return std::max(0ms, std::chrono::duration_cast<milliseconds>(delay));
136 if (m_explicitNextFrameTime)
137 return calculateInterval(*m_explicitNextFrameTime);
139 if (m_frames.front().isValid())
140 return calculateInterval(m_timeController.timeFromPosition(m_frames.front().absolutePts()));
142 if (m_lastFrameEnd > TrackPosition(0))
143 return calculateInterval(m_timeController.timeFromPosition(m_lastFrameEnd));
160 auto frame = m_frames.front();
169 const auto result = renderInternal(frame);
172 m_explicitNextFrameTime.reset();
175 if (frame.isValid()) {
176 m_lastPosition.storeRelease(std::max(frame.absolutePts(), lastPosition()).get());
179 m_lastFrameEnd = frame.absoluteEnd();
180 m_seekPos.storeRelaxed(m_lastFrameEnd.get());
182 const auto loopIndex = frame.loopOffset().loopIndex;
183 if (m_loopIndex < loopIndex) {
184 m_loopIndex = loopIndex;
185 emit loopChanged(id(), frame.loopOffset().loopStartTimeUs, m_loopIndex);
188 emit frameProcessed(frame);
190 m_lastPosition.storeRelease(std::max(m_lastFrameEnd, lastPosition()).get());
193 m_explicitNextFrameTime = SteadyClock::now() + result.recheckInterval;
196 setAtEnd(result.done && !frame.isValid());
198 scheduleNextStep(
false);
209 const auto now = SteadyClock::now();
210 const auto pos = m_timeController.positionFromTime(now);
211 m_timeController.sync(now + offset, pos);
212 emit synchronized(id(), now + offset, pos);