我想问题很简单。而且它更多的是数学而不是编码。 我从网络摄像头接收每秒15帧。但我不得不放弃其中一些。例如,如果客户端请求8 fps - 我确实会丢弃每个第二帧,并且没关系。但是如果要求12fps或6fps,我应该怎么下降?丢帧视频
我认为价值分布有一些共同的算法。非常感谢!
我想问题很简单。而且它更多的是数学而不是编码。 我从网络摄像头接收每秒15帧。但我不得不放弃其中一些。例如,如果客户端请求8 fps - 我确实会丢弃每个第二帧,并且没关系。但是如果要求12fps或6fps,我应该怎么下降?丢帧视频
我认为价值分布有一些共同的算法。非常感谢!
通过将每帧第2帧下降8 fps,如果您有15 fps,则会引入错误。
这是一个很简单的算法,这将适用于所有情况:
#include <iostream>
double t = 0.0;
const double fps1 = 15.0;
const double fps2 = 12.0;
const double t1 = 1.0/fps1;
const double t2 = 1.0/fps2;
// true - drop the frame
// false - do NOT drop the frame
bool NextTick()
{
t += t1;
if (t > t2)
{
t -= t2;
return false;
}
return true;
}
int main()
{
for (unsigned int i =0;i<20;++i)
{
if (NextTick())
{
std::cout<<"dropping the frame"<<std::endl;
}
else
{
std::cout<<"display the frame"<<std::endl;
}
}
}
我已经看到完成的方式(例如在gstreamer中)是有两个异步循环,一个接收来自摄像机的帧,另一个发送帧给客户端。后一个循环只有最近捕获的相机可用的帧,因此客户端没有“拾取”的帧会在下一个传入帧被覆盖时自动丢弃。
您需要做一点同步,以确保您不会读取一半的捕获帧,但除此之外它是一个直接的解决方案,并允许交换的两侧以不同方向以不同速度运行。
我不明白为什么每个人都把这个答案投给了?说循环 - 你的意思是线程?为我想的这么简单的任务添加一个线程并不好。它可以在一个和唯一的线程中处理。 – Dalamber 2010-11-22 04:45:59
@Dalamber是的,这是不好的。 – 2010-11-22 10:20:58
有一个环形缓冲区大到足以容纳1视频的全秒。
在这个缓冲区中写入每个视频帧。更新指向已写入的变量。
在一个单独的线程中使用一个定时器来延迟一段1000/desired_fps(84ms为12FPS),并挑选写入到最后一帧并发送。
我喜欢这个解决方案。但我不想再添加一个线程。 – Dalamber 2010-11-22 04:49:09
为什么不呢?杰西和我给出了非常相似的答案,这两个都需要一个线程。有时,即使情况很简单,简单的方法是使用一个线程。我在线程的安装和拆卸逻辑超过线程执行的内部逻辑的应用程序中有线程。无论如何,你可以使用相同的线程作为捕捉,但你冒着跳过你想发送的帧的风险。 – 2010-11-22 08:42:06
你能说这样的解决方案是什么:
我有0和1 15个静态常量字节数组。 1 - 显示帧,0 - 否。当我收到帧我增加计数器cnt = [0..15],看看它指向哪里 - 零或一。这就是我决定是显示还是丢帧。
我认为这个解决方案比实现新线程更容易,更快。
这种解决方案的作品,但我认为仍然可能有丢帧的风险,你不想放弃,因为如果你只有一个线程它将忙于从相机读取或写入输出最的时间,如果它在错误的时间做错了,你可能会错过一个传入的帧(取决于缓冲如何工作)。这个解决方案的另一个问题是,当你的网络摄像头坏掉时,你会购买一个开始发送24fps的新图片,或者你的客户想要显示10fps(例如)? – wjbeau 2010-11-22 10:05:34
通过这样做,你会引入大的舍入误差。但如果它适合您的需求,继续 – 2010-11-22 10:22:20
好吧,现在我看到您的解决方案更精确。但是我的速度要快3-4倍。现在 - 我会用我的。但无论如何,非常感谢! – Dalamber 2010-11-22 12:28:15
基本上你需要的是深入钻研FPS概念。
X的FPS表示一帧显示每隔1秒显示一次,并且它在显示屏上保持可见1/X秒。通常,帧在显示设备的每个垂直同步处在显示器上更新。
与此信息现在,帧速率转换可以被可视化为解码器解码,以临时显示在输入FPS并在输出FPS最终显示器上显示的帧采样。采样器从解码器正在更新帧的临时显示中采样帧。该逻辑应确保解码器和采样器之间的同步,使得采样器不会对部分更新的帧进行采样。
两个降低或提高FPS这个逻辑的工作。
这可以实现为具有同步访问的单个缓冲区。现在让解码器在输入FPS处写入此缓冲区,并从此缓冲区采样器拾取帧,并以输出fps显示。
这将确保屏幕更新是统一的,最新的可用框架显示在垂直同步。
我试过你的代码。但我也有fps2 = 15。并为循环高达15 * 10(10秒的视频,15fps)。在算法结束时,我有1帧丢失:)不好... – Dalamber 2010-11-22 04:47:25
上面的算法是限制FPS的标准方法。第一次检查很可能会有一些四舍五入。 – 2010-11-22 10:19:21
是的,我很抱歉 - 这看起来像是一些四舍五入的踢球。如果它比我的速度快 - 我会用它! //去检查 – Dalamber 2010-11-22 12:12:52