2012-04-26 491 views
5

我的WinForms .NET 4 C#应用程序会在用户与其交互时记录桌面。使用AForge.Video.FFMPEG/AForge.Video.VFW截屏视频。帧速率问题

它根据系统的速度使用AForge FFMPEG或VFW包装纸。捕捉是在后台线程中完成的。

在任何一种情况下,包装都要求预先指定帧速率。这是有问题的,因为捕捉频率是不确定的,并且容易受到目标机器繁忙程度的影响。在一个好的系统中,我最多可以获得10 FPS。

所以两个问题在这里:

  • 如何根据实际拍摄帧率对齐帧?
  • 如何增加帧率,也许通过使用AForge以外的解决方案?

我使用的代码如下列出了清晰:

private void ThreadWork() 
{ 
    int count = 0; 
    string filename = ""; 
    RECT rect = new RECT(); 
    System.Drawing.Bitmap bitmap = null; 
    System.Drawing.Graphics graphics = null; 
    System.DateTime dateTime = System.DateTime.Now; 
    System.IntPtr hWndForeground = System.IntPtr.Zero; 
    AForge.Video.FFMPEG.VideoFileWriter writer = null; 

    filename = @"c:\Users\Raheel Khan\Desktop\Temp\Capture.avi"; 
    if (System.IO.File.Exists(filename)) 
     System.IO.File.Delete(filename); 

    writer = new AForge.Video.FFMPEG.VideoFileWriter(); 
    writer.Open 
    (
     filename, 
     System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, 
     System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, 
     10, // FPS 
     AForge.Video.FFMPEG.VideoCodec.MPEG4 
    ); 

    bitmap = new Bitmap 
    (
     System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, 
     System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, 
     System.Drawing.Imaging.PixelFormat.Format24bppRgb 
    ); 
    graphics = System.Drawing.Graphics.FromImage(bitmap); 

    dateTime = System.DateTime.Now; 

    while (System.DateTime.Now.Subtract(dateTime).TotalSeconds < 10) // 10 seconds. 
    { 
     graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size); 

     rect = new RECT(); 
     hWndForeground = GetForegroundWindow(); 
     GetWindowRect(hWndForeground, ref rect); 
     graphics.DrawRectangle(Pens.Red, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top); 
     graphics.DrawString(count++.ToString(), this.Font, Brushes.Red, 10, 10); 

     writer.WriteVideoFrame(bitmap); 

     System.Threading.Thread.Sleep(10); 
    } 

    writer.Close(); 
    writer.Dispose(); 

    System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(filename)); 
} 

回答

3

你可以捕捉到的帧到一个临时文件夹中的JPEG文件或一个MJPEG文件,然后将其重新处理为AVI视频文件时用户需要它。这将减少您需要“即时”处理并释放资源的处理量,并让您的系统达到更高更正常的帧速率。

+0

谢谢。这将负责正确计算实际帧速率,但不幸的是,磁盘IO比现有方法需要更多时间。我在一个相当不错的开发机器上计时。我现在正在寻找像LeadTools这样的商业替代品,尽管它们的授权太贵了。 – 2012-04-28 09:27:54

+1

如果缓冲帧,则解决磁盘IO问题。以jpeg形式抓取每一帧并存储到内存中。 10mb的ram将存储约100帧,这是25fps 4秒。然后将它们作为具有MIME格式头的单个mjpeg文件写入磁盘。例如,Mencoder可以通过传递命令行参数直接将这样的文件转换为avi文件。这意味着你可以跳过伪造,并让你的avi在不同的过程中制作,这可以在多核机器中更节约资源。 – Sugrue 2012-04-28 09:44:57