C++ 丢弃视频帧

C++ 丢弃视频帧,c++,algorithm,frames,C++,Algorithm,Frames,我想我的问题很简单。它更多的是关于数学而不是编码。 我每秒从网络摄像机接收15帧。但我必须放弃一些。例如,如果客户机请求8帧/秒,我会删除每一帧,这样就可以了。但如果要求12 fps或6 fps,我应该如何放弃 我认为对于值分布有一些通用的算法。非常感谢 我看到这样做的方式,例如在gstreamer中,有两个异步循环,一个从相机接收帧,另一个将帧发送到客户端。后一个循环只有相机最近捕获的帧可用,因此客户端未拾取的帧在被下一个传入帧覆盖时自动删除 您需要进行一点同步,以确保不会读取半捕获的帧,但除

我想我的问题很简单。它更多的是关于数学而不是编码。 我每秒从网络摄像机接收15帧。但我必须放弃一些。例如,如果客户机请求8帧/秒,我会删除每一帧,这样就可以了。但如果要求12 fps或6 fps,我应该如何放弃


我认为对于值分布有一些通用的算法。非常感谢

我看到这样做的方式,例如在gstreamer中,有两个异步循环,一个从相机接收帧,另一个将帧发送到客户端。后一个循环只有相机最近捕获的帧可用,因此客户端未拾取的帧在被下一个传入帧覆盖时自动删除


您需要进行一点同步,以确保不会读取半捕获的帧,但除此之外,这是一个简单的解决方案,允许交换的两侧以不同的速度在任一方向上运行。

如果每2帧下降8帧,如果您的速度为15帧,则会引入错误

这是一个非常简单的算法,适用于所有情况:

#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;
      }
  }
}

有一个足够大的环形缓冲区来容纳1整秒的视频

将每个视频帧写入该缓冲区。更新指向已写入的变量


在一个单独的线程中,使用计时器将1000/所需的\u fps 84ms的时间延迟12fps,然后选择写入的最后一帧并发送该帧。

对于这种解决方案,您能说些什么:

我有15个0和1的静态常量字节数组。1-显示帧,0-否。当我收到帧时,我递增计数器cnt=[0..15],然后看它指向哪里-0或1。这就是我决定是显示还是删除帧的方式


我认为这个解决方案比实现新线程更简单、更快。

基本上,您需要深入了解FPS概念

FPS为X表示每1/X秒显示一帧,并且在显示器上保持可见1/X秒。通常,帧在显示设备的每次垂直同步时在显示器上更新

现在有了这些信息,帧速率转换可以可视化为解码器解码到输入FPS的临时显示,以及采样器在输出FPS的最终显示上显示帧。采样器从解码器正在更新帧的临时显示中采样帧。此逻辑应确保解码器和采样器之间的同步,以便采样器不会对部分更新的帧进行采样

该逻辑适用于减少或增加FPS

这可以实现为具有同步访问的单个缓冲区。现在,让解码器在输入FPS处写入该缓冲区,采样器从该缓冲区拾取帧并在输出FPS处显示


这将确保屏幕更新一致,并以垂直同步方式显示最新可用帧

我不明白为什么每个人都赞成这个答案?你说的循环是指线程吗?我认为为这么简单的任务添加一个线程是不好的。它只能在一个线程中处理。我已经尝试了你的代码。但我也有fps2=15。对于高达15*10秒的视频循环,每秒15帧。在algo结束时,我掉了1帧:不好……上面的算法是限制FPS的标准方法。很有可能是第一次检查时的一些舍入。是的,我很抱歉-这看起来真的像是舍入。如果它比我的快,我就用它//去检查我确信这件事没有考虑到帧可能以可变间隔出现。延迟在某些部分可能更大,在另一部分可能更小。如果tI喜欢此解决方案,则会错误地拒绝帧。但是我不喜欢多加一条线,为什么不呢?杰西和我给出了非常相似的答案,都需要一条线索。有时,即使情况很简单,最简单的方法还是使用线程。在应用程序中,线程的设置和拆卸逻辑超过了线程执行的内部逻辑。无论如何,您可以使用与捕获相同的线程,但您会冒跳过要发送的帧的风险。这种解决方案很有效,虽然我认为仍有可能丢失您不想丢失的帧,因为如果您只有一个线程,它将在大部分时间忙于从相机读取或写入输出,如果它在错误的时间执行错误的操作,根据缓冲的工作方式,可能最终会丢失传入帧。这个解决方案的另一个问题是,当你的网络摄像头坏了,你买了一个新的开始发送24fps的摄像头,或者你的客户想要显示10fps的摄像头时,会发生什么?这样做会引入很大的舍入误差。但是如果它适合你的需要,那就走吧好吧,现在我看到你的解决方案更精确了。但我的速度快了3-4倍。现在,我要用我的。但无论如何,非常感谢!
问题不在于屏幕