isA*_*Don 3 c++ c++11 c++-chrono
我正在使用OpenCV来编写视频文件.为了cv::VideoWriter正常工作,对write()函数的调用必须每秒发生30次(对于30fps视频).我发现这个代码使用boost库来实现这一点.我想要同样但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();
Run Code Online (Sandbox Code Playgroud)
我不确定这是否是正确的方法,或者是否有更有效的方法.还有什么比投射持续时间更好的long long difference?
How*_*ant 12
有一个基本租户可以使用chrono,它类似于:
如果你使用
count(),和/或你的chrono代码中有转换因子 ,那么你就是在努力.
这不是你的错.确实没有好的chrono教程,这是我的不好,我最近决定我需要做些什么.
在您的情况下,我建议您按照以下方式重写代码:
首先创建一个持续时间单位,表示帧速率的周期:
using frame_period = std::chrono::duration<long long, std::ratio<1, 30>>;
Run Code Online (Sandbox Code Playgroud)
现在,当你说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();
Run Code Online (Sandbox Code Playgroud)
一旦你得到计时,上面的评论就过于冗长了.评论比上面的代码更多.但是上面的工作正如你想象的那样,不需要"逃出"计时系统.
更新
如果你想初始化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;
}
Run Code Online (Sandbox Code Playgroud)
ceilduration_cast当转换不精确时,它将取代它,而不是截断为零.现在你可以说:
auto difference = ceil<hr_duration>(frame_period{1});
Run Code Online (Sandbox Code Playgroud)
你保证这一点difference >= frame_period{1}.此外,实际上已知high_resolution_clock的持续时间为纳秒,因此您可以推导(或测试)difference实际初始化为33,333,334ns,即大于1/30秒的2/3纳秒,等于frame_period{1},等于33,333,333 + 1/3ns.