如何在Hololens上使用多线程

时间:2019-11-05 12:20:35

标签: c# multithreading unity3d hololens

我们正在尝试在Hololens上使用多线程,但是失败了。 由于我们不知道如何以及在附加线程中实现什么。

当前,我们的应用程序正在主线程中运行许多操作,如果我们启动“实时流”(与WebcamTexture一起使用),全息图将不再显示。

因此,从一开始,我们想问一下如何使用线程更有效地运行图像捕获代码的一部分(如下所示)?这样我们就可以了解哪些部分可以在不同的线程中运行。

我们正在使用Unity 2018.4.10f1

using UnityEngine;
using System.Linq;
using UnityEngine.XR.WSA.WebCam;

public partial class PhotocaptureFrame : MonoBehaviour
{

    public PhotoCapture photoCaptureObject = null;
    public GameObject quad;

    public static PhotocaptureFrame Instance { get; set; }

    private Texture2D imageTexture;
    private CameraParameters c;
    private Resolution cameraResolution;

    private void Start()
    {
        cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

        PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
        {
            photoCaptureObject = captureObject;

            //CameraParameters c = new CameraParameters();
            c.hologramOpacity = 0.0f;
            c.cameraResolutionWidth = cameraResolution.width;
            c.cameraResolutionHeight = cameraResolution.height;
            c.pixelFormat = CapturePixelFormat.BGRA32;

            captureObject.StartPhotoModeAsync(c, delegate (PhotoCapture.PhotoCaptureResult result)
            {
                photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
            });

        });

        Instance = this;
    }

    public void MakePhoto()
    {
        PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

    captureObject.StartPhotoModeAsync(c, delegate (PhotoCapture.PhotoCaptureResult result)
    {
        photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
    });

});

    }

    public void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
    {

        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First(); // Create our Texture2D for use and set the correct resolution
        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);

        photoCaptureFrame.UploadImageDataToTexture(targetTexture);  // Copy the raw image data into our target texture

        imageTexture = targetTexture;       //Save image to new Texture to not loose it

        quad.GetComponent<Renderer>().material.mainTexture = imageTexture;     // Do as we wish with the texture such as apply it to a material, etc.
                                                                               //photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoModeEnd);


        // Clean up
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoModeEnd);
    }

    public void OnStoppedPhotoModeEnd(PhotoCapture.PhotoCaptureResult result)
    {
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
        Debug.Log("Photo object disposed.");

    }
}

我们的预期输出是知道我们可以在不同线程中运行哪些块,以及如何在Hololens上调用不同线程。

感谢分配,感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

尽管这不能直接回答您的问题,但我真的可以推荐此插件:HololensCameraStream,该插件内部使用MediaCapture类。 帧是异步获取的,这意味着Videocapture本身实际上在其自己的线程中运行。此外,与使用PhotoCapture的方法相比,性能更好(可以获取更多帧)。 您将在回调函数中获得每一帧。

由于此回调未在Unity主线程上运行,因此您将需要利用某种作业系统来调用Unity函数。我使用了这个方便的脚本:https://github.com/PimDeWitte/UnityMainThreadDispatcher

如果这有帮助,并且您还有其他问题,我可以添加更多有关如何进行设置的详细信息。

答案 1 :(得分:0)

        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);

        ...

        quad.GetComponent<Renderer>().material.mainTexture = imageTexture; 

您只能在Unity的主线程上创建和分配纹理。正确且唯一的解决方案是调查WebCamTexture。您可能会遇到权限问题。

答案 2 :(得分:0)

我建议您异步使用MediaCapture类进行视频流捕获。在实际示例中,Microsoft HoloLensCamera中的SpectatorView类使用MediaCapture类访问HoloLens摄像机的视频流。在861行中,它声明MediaCapture类的实例,并在下一个代码中异步地从摄像机获取视频帧。