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