gpt4 book ai didi

c# - 使用 DirectX Texture2D 显示相机预览会导致 Windows Phone 8 出现振荡

转载 作者:太空宇宙 更新时间:2023-11-03 13:35:50 25 4
gpt4 key购买 nike

我目前正在编写一个小应用程序,它使用 SharpDX Sprite 批处理显示手机摄像头的预览。有nokia开发者账号的 friend ,代码主要来自this article .

问题

偶尔,似乎前几帧被绘制到屏幕上(“视频”来回跳动),因为一秒钟的断裂,看起来像振荡/闪烁。

我想到了一个线程问题(因为 PreviewFrameAvailable 事件处理程序是由不同的线程调用的,而不是负责渲染的方法),但是在这两个方法中插入一个 lock 语句会使代码太慢(帧速率低于15 帧/秒)。

有没有人知道如何解决这个问题或如何在这种情况下实现线程同步而不损失太多性能?

代码

首先,创建所有资源,而设备是 GraphicsDevice 的有效实例:

spriteBatch = new SpriteBatch(device);
photoDevice = await PhotoCaptureDevice.OpenAsync(CameraSensorLocation.Back, captureSize);
photoDevice.FocusRegion = null;

width = (int)photoDevice.PreviewResolution.Width;
height = (int)photoDevice.PreviewResolution.Height;

previewData = new int[width * height];

cameraTexture = Texture2D.New(device, width, height, PixelFormat.B8G8R8A8.UNorm);

photoDevice.PreviewFrameAvailable += photoDevice_PreviewFrameAvailable;

然后,每当预览帧发生变化时,我将数据设置为纹理:

void photoDevice_PreviewFrameAvailable(ICameraCaptureDevice sender, object args)
{
sender.GetPreviewBufferArgb(previewData);
cameraTexture.SetData(previewData);
}

最后,使用 SpriteBatch 绘制纹理,而参数 backBufferCenter、textureCenter、textureScaling 和 Math.Pi/2 用于横向居中和调整纹理:

spriteBatch.Begin();

spriteBatch.Draw(cameraTexture, backBufferCenter, null, Color.White, (float)Math.PI / 2, textureCenter, textureScaling, SpriteEffects.None, 1.0f);

spriteBatch.End();

render 方法由 SharpDX 游戏类调用,它基本上使用 IDrawingSurfaceBackgroundContentProvider 接口(interface),即 called by the DrawingSurfaceBackgroundGrid Windows Phone 8 运行时的组件。

解决方案

除了 Olydis 解决方案(见下文)之外,由于 SharpDX 错误,我还必须将 Game.IsFixedTimeStep 设置为 false(有关详细信息,请参见 issue on GitHub)。

此外,由于跨线程访问,在 PreviewFrameAvailable 的处理程序中调用 sender.GetPreviewBufferArgb(previewData)安全的。请参阅 windows phone developer community 中的相应线程.

最佳答案

我的猜测

如您所料,我也很确定这可能是线程造成的。我怀疑,例如,相对冗长的 SetData 调用可能会被 Draw 调用拦截,从而导致意外输出。

解决方案

以下解决方案不使用同步,而是将“关键”部分(访问纹理)移动到相同的上下文。

另外,让我们分配两个 int[] 而不是一个,我们将以交替方式使用它们。

代码片段

void photoDevice_PreviewFrameAvailable(ICameraCaptureDevice sender, object args)
{
sender.GetPreviewBufferArgb(previewData2);
// swap buffers
var previewDataTemp = previewData1;
previewData1 = previewData2;
previewData2 = previewDataTemp;
}

然后将此添加到您的 Draw 调用(或同等上下文):

cameraTexture.SetData(previewData1);

结论

这应该实际上可以防止您的问题,因为只绘制“完全更新”的纹理并且没有并发访问它们。使用两个 int[] 降低了 SetDataGetPreviewBufferArgb 同时访问同一个数组的风险 - 但是,它不会消除风险(但不知道并发访问 int[] 是否首先会导致奇怪的行为)。

关于c# - 使用 DirectX Texture2D 显示相机预览会导致 Windows Phone 8 出现振荡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18740980/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com