如何使用 XNA 将一系列图像从 ui 线程获取到 Silverlight 5 中的绘制线程
在 Silverlight 中,我试图获取在一系列 3d 四边形上纹理化的网络摄像头(实时)流的帧。我在网络摄像头控制器类中的网络摄像头控制器类中使用 VideoSink。然后我在 DrawingSurface 中绘制四边形。但我继续在 CrossAppDomainMarshaledException 中运行。作为解决方案,我尝试使用 Dispatcher.BeginInvoke 但有时 BeginInvoke 中的代码似乎会跳过或跳出线程。一个人如何处理这样的事情呢?
//Video sink capture
// Is called every time the webcam provides a complete frame (Push)
protected override void OnSample(long sampleTime, long frameDuration, byte[] sampleData)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
WriteableBitmap bmp = new WriteableBitmap(vidFormat.PixelWidth, vidFormat.PixelHeight);
RaiseFrameCapture(new FrameCapturedEventArgs { Frame = bmp.FromByteArray(sampleData) });
});
}
//Capture from sink into WebCamController
void sink_FrameCaptured(object sender, FrameCapturedEventArgs e)
{
//List<WriteableBitmap>
_WebCamSource.AddImage(e.Frame.Clone());
}
//XNA draw event handler
private void DrawingSurface_Draw(object sender, DrawEventArgs e)
{
List<WriteableBitmap> frames = new List<WriteableBitmap>();
if (webCamSource.Frames.Count > 0)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
frames = new List<WriteableBitmap>(webCamSource.Frames.ToArray());
});
}
Draw(frames);
e.InvalidateSurface();
}
in Silverlight I'm trying to get the frames of a webcam (live) stream textured on a series of 3d quads. I use a VideoSink in a webcam controller class in a webcam controller class. Then i draw the quads in the DrawingSurface. But I keep running in CrossAppDomainMarshaledException. As a solution I try to use the Dispatcher.BeginInvoke but sometimes the code in the BeginInvoke seems to jump over or out of the thread. How does one approach things like this?
//Video sink capture
// Is called every time the webcam provides a complete frame (Push)
protected override void OnSample(long sampleTime, long frameDuration, byte[] sampleData)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
WriteableBitmap bmp = new WriteableBitmap(vidFormat.PixelWidth, vidFormat.PixelHeight);
RaiseFrameCapture(new FrameCapturedEventArgs { Frame = bmp.FromByteArray(sampleData) });
});
}
//Capture from sink into WebCamController
void sink_FrameCaptured(object sender, FrameCapturedEventArgs e)
{
//List<WriteableBitmap>
_WebCamSource.AddImage(e.Frame.Clone());
}
//XNA draw event handler
private void DrawingSurface_Draw(object sender, DrawEventArgs e)
{
List<WriteableBitmap> frames = new List<WriteableBitmap>();
if (webCamSource.Frames.Count > 0)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
frames = new List<WriteableBitmap>(webCamSource.Frames.ToArray());
});
}
Draw(frames);
e.InvalidateSurface();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
即使您解决了问题,我也许可以提供一些见解。 XNA 与经典的 Silverlight 渲染有很大不同。
在经典的 Silverlight 渲染管道中,您以声明方式构建可视化树,并将更改推送到它。渲染循环在看不见的地方运行,您很少需要打扰它。
因此,您希望尽快将更改推送到可视化树。如果您在 UI 线程(正在运行的线程)之外的其他线程中更新可视化树,则更新可能会在渲染期间发生,这将是灾难性的。因此,UI 线程公开了一个消息泵,可通过 Dispatcher.BeginInvoke 使用,以确保线程安全。
使用 XNA,您就没有这些...因为您实现了自己的渲染管道,并且可以完全控制它。
每次处理网络摄像头帧时,将其设置在网络摄像头控制器中(使用锁)。在每个 XNA 帧中,如果网络摄像头控制器收到新帧,则获取网络摄像头帧(使用锁)并更新 XNA 纹理(不要为每个帧创建新纹理,这样效率不高)。然后,使用该纹理渲染 3D 对象。
Even if you solved your issue, I can maybe provide some insight. XNA is quite different from classical Silverlight rendering.
In the classical Silverlight rendering pipeline, you declaratively build the visual tree, and push your changes to it. The rendering loop is running out of sight, and you rarely have to mess with it.
Therefore, you want to push your changes to the visual tree as soon as possible. If you update the visual tree in an other thread than the UI thread (the one running), the update could happen during rendering, which would be catastrophic. Therefore the UI thread exposes a message pump, useable through Dispatcher.BeginInvoke, to ensure thread safety.
With XNA, you don't have any of this... Because you implement your own rendering pipeline, and have full control on it.
Each time you process a webcame frame, set it in an your webcam controller (using a lock). In each XNA frame, if the webcam controller received a new frame, get the webcam frame (using the lock) and update a XNA texture (don't create a new texture for each frame, it's NOT efficient). Then, render your 3D object using this texture.