Skip to content

Commit

Permalink
clock;
Browse files Browse the repository at this point in the history
  • Loading branch information
RealChuan committed Aug 27, 2023
1 parent 7a99b2b commit b7f1f6c
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ffmpeg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ set(PROJECT_SOURCES
averror.h
averrormanager.cc
averrormanager.hpp
clock.cc
clock.hpp
codeccontext.cpp
codeccontext.h
colorspace.hpp
Expand Down
139 changes: 139 additions & 0 deletions ffmpeg/clock.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include "clock.hpp"

#include <QMutex>

extern "C" {
#include <libavutil/time.h>
}

namespace Ffmpeg {

class Clock::ClockPrivate
{
public:
explicit ClockPrivate(Clock *q)
: q_ptr(q)
{}

Clock *q_ptr;

mutable QMutex mutex;
qint64 pts = 0; // 当前 AVFrame 的时间戳 microseconds
qint64 pts_drift = 0; // 时钟漂移量,用于计算当前时钟的状态 microseconds
qint64 last_updated = av_gettime_relative(); // 上一次更新时钟状态的时间 microseconds
bool paused = false; // 是否暂停播放

static constexpr QPair<double, double> speedRange = {0.5, 3.0};
static constexpr auto speedStep = 0.5;
static std::atomic<double> speed;

static constexpr auto diffThreshold = 50 * 1000; // 50ms

static Clock *g_clock;
};

std::atomic<double> Clock::ClockPrivate::speed = 1.0;
Clock *Clock::ClockPrivate::g_clock = nullptr;

Clock::Clock(QObject *parent)
: QObject{parent}
, d_ptr(new ClockPrivate(this))
{}

Clock::~Clock() = default;

auto Clock::pts() -> qint64
{
QMutexLocker locker(&d_ptr->mutex);
return d_ptr->pts;
}

auto Clock::ptsDrift() -> qint64
{
QMutexLocker locker(&d_ptr->mutex);
return d_ptr->pts_drift;
}

auto Clock::lastUpdated() -> qint64
{
QMutexLocker locker(&d_ptr->mutex);
return d_ptr->last_updated;
}

auto Clock::paused() -> bool
{
QMutexLocker locker(&d_ptr->mutex);
return d_ptr->paused;
}

void Clock::setPaused(bool value)
{
QMutexLocker locker(&d_ptr->mutex);
d_ptr->paused = value;
if (!d_ptr->paused) {
d_ptr->last_updated = av_gettime_relative();
}
}

void Clock::update(qint64 pts, qint64 time)
{
QMutexLocker locker(&d_ptr->mutex);
if (d_ptr->last_updated && !d_ptr->paused) {
qint64 time_diff = (time - d_ptr->last_updated) * speed();
d_ptr->pts_drift = (pts - d_ptr->pts) - time_diff;
}
d_ptr->pts = pts;
d_ptr->last_updated = time;
}

auto Clock::getDelayWithMaster() -> qint64
{
Q_ASSERT(Clock::ClockPrivate::g_clock);
auto pts_drift = ptsDrift();
if (this == Clock::ClockPrivate::g_clock) {
return pts_drift;
}
pts_drift -= Clock::ClockPrivate::g_clock->ptsDrift();
return pts_drift;
}

auto Clock::adjustDelay(qint64 &delay) -> bool
{
if (speed() > 1.0 && delay < 0) {
return false;
} else if (delay < -Clock::ClockPrivate::diffThreshold) {
return false;
} else if (qAbs(delay) <= Clock::ClockPrivate::diffThreshold) {
delay = 0;
return true;
}
delay -= Clock::ClockPrivate::diffThreshold;
return true;
}

auto Clock::speedRange() -> QPair<double, double>
{
return Clock::ClockPrivate::speedRange;
}

auto Clock::speedStep() -> double
{
return Clock::ClockPrivate::speedStep;
}

void Clock::setSpeed(double value)
{
Clock::ClockPrivate::speed.store(value);
}

auto Clock::speed() -> double
{
return Clock::ClockPrivate::speed.load();
}

void Clock::setMaster(Clock *clock)
{
Clock::ClockPrivate::g_clock = clock;
}

} // namespace Ffmpeg
43 changes: 43 additions & 0 deletions ffmpeg/clock.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef CLOCK_HPP
#define CLOCK_HPP

#include <QObject>

namespace Ffmpeg {

class Clock : public QObject
{
public:
explicit Clock(QObject *parent = nullptr);
~Clock() override;

auto pts() -> qint64;
auto ptsDrift() -> qint64;
auto lastUpdated() -> qint64;

void setPaused(bool value);
auto paused() -> bool;

void update(qint64 pts, qint64 time);

auto getDelayWithMaster() -> qint64;

// return true if delay is valid
static auto adjustDelay(qint64 &delay) -> bool;

auto speedRange() -> QPair<double, double>;
auto speedStep() -> double;
static void setSpeed(double value);
static auto speed() -> double;

// not thread safe and not delete clock
static void setMaster(Clock *clock);

private:
class ClockPrivate;
QScopedPointer<ClockPrivate> d_ptr;
};

} // namespace Ffmpeg

#endif // CLOCK_HPP
2 changes: 2 additions & 0 deletions ffmpeg/ffmpeg.pro
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ SOURCES += \
avcontextinfo.cpp \
averror.cpp \
averrormanager.cc \
clock.cc \
codeccontext.cpp \
decoder.cc \
decoderaudioframe.cpp \
Expand All @@ -44,6 +45,7 @@ HEADERS += \
avcontextinfo.h \
averror.h \
averrormanager.hpp \
clock.hpp \
codeccontext.h \
colorspace.hpp \
decoder.h \
Expand Down

0 comments on commit b7f1f6c

Please sign in to comment.