使用 std::chrono::high_resolution_clock 每秒写入帧 30 次
using std::chrono::high_resolution_clock to write a frame 30 times per second
我正在使用OpenCV编写视频文件。为了使cv::VideoWriter
正常工作,对 write() 函数的调用必须每秒发生 30 次(对于 30fps 视频)。我找到了这段代码,它使用提升库来实现这一点。我想做同样的事情,但在我的程序中使用std::chrono
。这是我的实现:
std::chrono::high_resolution_clock::time_point prev = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point current = prev;
long long difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
while(recording){
while (difference < 1000000/30){
current = std::chrono::high_resolution_clock::now();
difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
}
theVideoWriter.write(frameToRecord);
prev = prev + std::chrono::high_resolution_clock::duration(1000000000/30);
difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
}
theVideoWriter.release();
我不确定这是否是正确的方法,或者是否有更有效的方法。有什么比将持续时间投射到long long difference
更好的吗?
有一个基本的租户来使用 chrono
,它类似于:
如果您使用
count()
和/或您的chrono
代码,那么你就太努力了。
这不是你的错。 真的没有好的chrono
教程,这是我的坏处,我最近决定我需要为此做点什么。
在您的情况下,我建议按以下方式重写代码:
首先创建一个表示帧速率周期的持续时间单位:
using frame_period = std::chrono::duration<long long, std::ratio<1, 30>>;
现在当你说frame_period{1}
,这意味着正好是 1/30 秒。
接下来要注意的是,只要您停留在计时系统中,chrono
比较总是准确的。 count()
是逃出计时系统的"活板门"。 只有在别无选择的情况下才能逃脱。 所以。。。
auto prev = std::chrono::high_resolution_clock::now();
auto current = pref;
// Just get the difference, and don't worry about the units for now
auto difference = current-prev;
while(recording)
{
// Find out if the difference is less than one frame period
// This comparison will do all the conversions for you to get an exact answer
while (difference < frame_period{1})
{
current = std::chrono::high_resolution_clock::now();
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.write(frameToRecord);
// This is a little tricky...
// prev + frame_period{1} creates a time_point with a complicated unit
// Use time_point_cast to convert (via truncation towards zero) back to
// the "native" duration of high_resolution_clock
using hr_duration = std::chrono::high_resolution_clock::duration;
prev = std::chrono::time_point_cast<hr_duration>(prev + frame_period{1});
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.release();
一旦你得到时间,上面的评论就过于冗长了。 有比上面的代码更多的注释。 但以上只是按您的预期工作,无需"逃脱"计时系统。
更新
如果要初始化difference
以便第一次不会执行内部循环,则可以将其初始化为刚好超过 frame_period{1}
的值,而不是 0。 为此,此处找到的实用程序派上用场。 具体ceil
:
// round up
template <class To, class Rep, class Period>
To
ceil(const std::chrono::duration<Rep, Period>& d)
{
To t = std::chrono::duration_cast<To>(d);
if (t < d)
++t;
return t;
}
ceil
是 duration_cast
的替代品,当转换不精确时,将四舍五入,而不是截断为零。 现在你可以说:
auto difference = ceil<hr_duration>(frame_period{1});
而且您保证difference >= frame_period{1}
. 此外,在实践中已知high_resolution_clock的持续时间为纳秒,因此您可以推断(或测试)difference
实际上初始化为 33,333,334ns,即比 1/30 秒大 2/3 纳秒,等于 frame_period{1}
,等于 33,333,333+1/3ns。
- 从持续时间构造std::chrono::system_clock::time_point
- 如何在c++迭代器类型中包装std::chrono
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用 SendInput 或 mouse_event 不适用于 clock()?
- 使用 memcpy() 复制到 std::chrono::milliseconds 会给出错误 -Werror=clas
- std::multimap<std::chrono::milliseconds, T>::rbegin 在 MSVS-13 中指向 end()?
- 如何在C++中将 chrono::秒转换为 HH:MM:SS 格式的字符串?
- C++ Chrono 确定一天是否是周末?
- std::adjacent_difference with std::chrono time_point
- VSCode 说 std::chrono 是模棱两可的,如果运算符<<重载
- 是否确保 2 个连续的 std::chrono::steady_clock::now() 不相等?
- std::chrono::d uration 可以按秒初始化,但不能按毫秒初始化?
- chrono::month 和 chrono::month 有什么区别
- 比较两个 std::chrono::time_point 实例时出错
- 来自 std::chrono 的编译器警告,但未被使用
- 从编译时已知的日历日期创建"std::chrono::time_point"
- std::chrono::time_point from std::string
- 使用 std::chrono::steady_clock 对线程/异步中的代码进行基准测试
- 为什么 std::chrono 在测量循环和编译器优化的并行 OpenMP 的执行时间时不起作用?
- 测量执行时间-gettimeofday与clock()与chrono