【发布时间】:2010-11-19 09:45:49
【问题描述】:
我想我的问题很简单。它更多的是关于数学而不是编码。 我每秒从网络摄像头接收 15 帧。但我必须放弃其中的一些。例如,如果客户端请求 8 fps - 我确实每秒丢弃一帧,这没关系。但是,如果请求 12 fps 或 6 fps,我应该如何丢弃?
我认为有一些常见的价值分配算法。非常感谢!
【问题讨论】:
我想我的问题很简单。它更多的是关于数学而不是编码。 我每秒从网络摄像头接收 15 帧。但我必须放弃其中的一些。例如,如果客户端请求 8 fps - 我确实每秒丢弃一帧,这没关系。但是,如果请求 12 fps 或 6 fps,我应该如何丢弃?
我认为有一些常见的价值分配算法。非常感谢!
【问题讨论】:
我看到的方式(例如在 gstreamer 中)是有两个异步循环,一个从相机接收帧,一个将帧发送到客户端。后一个循环仅具有可用的相机最近捕获的帧,因此客户端未“拾取”的帧将被自动丢弃,因为它们被下一个传入帧覆盖。
您需要进行一些同步以确保您不会读取一半捕获的帧,但除此之外,这是一个直接的解决方案,并允许交换的两侧在任一方向上以不同的速度运行。
【讨论】:
基本上,您需要深入了解 FPS 概念。
X 的 FPS 意味着每 1/X 秒显示一帧,并在显示器上保持可见 1/X 秒。通常,这些帧会在显示设备的每次垂直同步时在显示器上更新。
现在有了这些信息,可以将帧速率转换可视化为解码器解码以临时显示在输入 FPS 和采样器在输出 FPS 的最终显示上显示帧。采样器从解码器正在更新帧的临时显示器中采样帧。此逻辑应确保解码器和采样器之间的同步,以便采样器最终不会对部分更新的帧进行采样。
此逻辑适用于降低或提高 FPS。
这可以实现为具有同步访问的单个缓冲区。现在让解码器以输入 FPS 写入该缓冲区,采样器从该缓冲区中挑选帧并以输出 fps 显示。
这将确保屏幕更新一致,并以垂直同步显示最新的可用帧。
【讨论】:
通过每 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;
}
}
}
【讨论】:
有一个足够大的环形缓冲区来容纳一整秒的视频。
将每个视频帧写入此缓冲区。更新指向已写入的变量。
在单独的线程中,使用计时器延迟 1000 / desired_fps 的周期(12fps 为 84 毫秒),然后选择写入的最后一帧并发送。
【讨论】:
你对这样的解决方案有什么看法:
我有 15 个带有 0 和 1 的静态 const 字节数组。 1 - 显示帧,0 - 否。当我收到帧时,我增加计数器 cnt = [0..15] 并查看它指向的位置 - 零或一。这就是我决定是显示还是丢帧的方式。
我认为这个解决方案比实现新线程更容易和更快。
【讨论】: