Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在WPF中生成和绘制视频的快速方法是什么?_C#_Wpf_Video Processing - Fatal编程技术网

C# 在WPF中生成和绘制视频的快速方法是什么?

C# 在WPF中生成和绘制视频的快速方法是什么?,c#,wpf,video-processing,C#,Wpf,Video Processing,我正在写一个视频播放器来播放我们的ASIC捕获的帧。它们是自定义格式的,我已经获得了一个解码ASIC状态的功能。视频可以是从640x480到2560x1200的任何大小(!!!)。每个状态周期的输出是一个16x16像素块,我必须把它放到屏幕上的视频中 每次需要更新屏幕时,我都有以下信息: 块宽度 块高 块起点的X坐标 块起点的Y坐标 RGB32像素颜色信息的一维阵列 主要限制: .NET 3.5 没有不安全的代码 今天早上我试用了一个WriteableBitmap,并将其用作图像的源,类

我正在写一个视频播放器来播放我们的ASIC捕获的帧。它们是自定义格式的,我已经获得了一个解码ASIC状态的功能。视频可以是从640x480到2560x1200的任何大小(!!!)。每个状态周期的输出是一个16x16像素块,我必须把它放到屏幕上的视频中

每次需要更新屏幕时,我都有以下信息:

  • 块宽度
  • 块高
  • 块起点的X坐标
  • 块起点的Y坐标
  • RGB32像素颜色信息的一维阵列
主要限制:

  • .NET 3.5
  • 没有不安全的代码
今天早上我试用了一个WriteableBitmap,并将其用作图像的源,类似这样:

    private WriteableBitmap ImageSource;

    public MainWindow()
    {
        InitializeComponent();

        ImageSource = new WriteableBitmap(FrameWidth, FrameHeight, 96, 96, PixelFormats.Bgr32, null);
        ImagePanel.Source = ImageSource;
    }

    private void DrawBox(byte Red, byte Green, byte Blue, int X, int Y)
    {
        int BoxWidth = 16;
        int BoxHeight = 16;
        int BytesPerPixel = ImageSource.Format.BitsPerPixel / 8;

        byte[] Pixels = new byte[BoxWidth * BoxHeight * BytesPerPixel];

        for (int i = 0; i < Pixels.Length; i += 4)
        {
            Pixels[i + 0] = Blue;
            Pixels[i + 1] = Green;
            Pixels[i + 2] = Red;
            Pixels[i + 3] = 0;
        }

        int Stride = BoxWidth * BytesPerPixel;
        Int32Rect DrawBox = new Int32Rect(X, Y, BoxWidth, BoxHeight);

        ImageSource.Lock();
        ImageSource.WritePixels(DrawBox, Pixels, Stride, 0);
        ImageSource.Unlock();
    }
private WriteableBitmap-ImageSource;
公共主窗口()
{
初始化组件();
ImageSource=新的WriteableBitmap(帧宽、帧高、96、96、PixelFormats.Bgr32、null);
ImagePanel.Source=ImageSource;
}
专用空抽屉(字节红色、字节绿色、字节蓝色、整数X、整数Y)
{
int-BoxWidth=16;
int-BoxHeight=16;
int BytesPerPixel=ImageSource.Format.BitsPerPixel/8;
字节[]像素=新字节[BoxWidth*BoxHeight*BytesPerPixel];
对于(int i=0;i

它可以工作,我的视频可以在屏幕上播放,但是很慢。远不及实时播放速度。除了按程序生成一系列位图之外,还有没有更好的方法来完成我没有看到的任务?我读过一些关于D3Dimage的文章,但它似乎更适合将3D场景导出为位图。这里的建议?

如果我理解正确,您将收到一个16*16像素的块作为捕获,在上面的示例中,您将在每次更新时更新可写位图

这看起来像是在每个块上触发渲染时的大量搅动

是否最好是:

  • 维护表示整个帧的单字节缓冲区
  • 当您收到16*16块时,用它们更新缓冲区
  • 接收到一帧的所有块后,将缓冲区写入位图
  • 通过重写下一帧,重新使用该帧缓冲区
通过这种方式,渲染时的波动会小得多,因为您不会为接收到的每个块触发渲染,而只为每个帧触发渲染

更新1

我也会考虑使用BGR24作为你的像素格式,如果你不使用alpha通道。这样,每个像素将有3个字节,而不是4个字节,因此开销大大减少

更新2

如果对于更大的帧大小,情况仍然太慢,您也可以考虑以下内容,这会增加复杂性。

考虑维护和翻转两个帧缓冲区。通过这种方式,您可以在后台线程上合成帧,然后在UI线程上blit完成的帧。当UI线程渲染帧时,您可以继续在备用缓冲区上进行合成

更新3


如果捕获的像素颜色信息数组的格式正确,可以尝试使用将源像素数组批量复制到帧缓冲区数组中。不过,您必须将位图格式保持为bgr32。这种低级阵列复制技术可能会带来一些性能提升。

DrawBox似乎正在创建一个16*16像素的纯色块。这是正确的吗?使用WriteableBitmap.WritePixels方法(Int32Rect、Array、Int32、Int32、Int32),您不需要使用锁定和解锁源代码:是的,DrawBox是我用来绘制纯色块的工具。另外,谢谢你的锁定,我想我应该仔细阅读。你是使用3.5和SP1吗?应该为WriteableBitmap提供了一个性能修复程序。另外,你是在XP上运行的吗?根据我有限的经验,WPF在Vista和更高版本上运行得更好。谢谢!使用Buffer.BlockCopy在后台构建缓冲区,然后每帧调用一次WritePixels(),就成功了!