PhotoCaputure 导致 Unity 内存泄漏

PhotoCaputure causes memory leak in Unity

我正在使用 unity 的 Photocapture Object 用全息镜头拍摄视频。 我根据官方示例代码编写了代码,但我将更新功能中的过程更改为拍摄多张图片而不是一张。

https://docs.unity3d.com/2018.4/Documentation/Manual/windowsholographic-photocapture.html

但是,当我 运行 这段代码时,它最终 运行 超出 pagefile.sys、内存不足并中止。 我已经搜索并发现大部分内存泄漏是由纹理 2d 引起的,但是在这段代码中,即使我省略了它们,它们也会发生。此外,unity profiler 没有显示代码执行后内存使用量逐渐增加。 可能是什么原因?如果你能告诉我,我将不胜感激。

using UnityEngine;
using System;
using System.Linq;
using UnityEngine.XR;
using UnityEngine.Windows.WebCam;
using System.Threading.Tasks;
using UnityEngine.Networking;
using System.Text;
using System.IO;
using System.Net;
using System.Collections;
using System.Collections.Generic;

public class photocap : MonoBehaviour
{
    PhotoCapture PhotoCapture = null;
    Texture2D targetTexture = null;
    Resolution cameraResolution;
    Renderer quadRenderer;
    float dt = 0;



    void Start()
    {
        cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
        quad.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
        quadRenderer = quad.GetComponent<Renderer>() as Renderer;
        quadRenderer.material = new Material(Shader.Find("Unlit/Texture"));


        quad.transform.parent = this.transform;
        quad.transform.localPosition = new Vector3(0.0f, 0.0f, 0.3f);

    }


    async void StartCapture()
    {


        PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
        {
            PhotoCapture = captureObject;
            CameraParameters cameraParameters = new CameraParameters();
            cameraParameters.hologramOpacity = 0.0f;
            cameraParameters.cameraResolutionWidth = cameraResolution.width;
            cameraParameters.cameraResolutionHeight = cameraResolution.height;
            cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;


            PhotoCapture.StartPhotoModeAsync(cameraParameters, delegate (PhotoCapture.PhotoCaptureResult result)
            {

                PhotoCapture.TakePhotoAsync(OnCapturedPhotoToMemory);
            });
        });
    }

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



        PhotoCapture.StopPhotoModeAsync(OnStoppedPhotoMode);


    }

    void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
    {

        PhotoCapture.Dispose();
        PhotoCapture = null;
    }
    void Update()
    {
        dt += Time.deltaTime;

        if (dt > 3)
        {
            dt = 0.0f;
            StartCapture();
        }

    }



}

我很确定你也 want/have 处理 photoCaptureFrame!

否则存储的纹理将永远保留在您的应用程序内存中。

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    // TODO: Obviously you first would want to do something with the just captured image ...

    photoCaptureFrame.Dispose();

    PhotoCapture.StopPhotoModeAsync(OnStoppedPhotoMode);
}

哦还有一件事:

您目前正在根据经过的时间开始新的捕获。

如果拍照、处理数据和处理的时间超过该间隔会怎样?

您可能宁愿仅在第一次捕获实际完全完成后才触发新的捕获延迟!

实际上为什么还要一直创建、启动、停止和处理捕获?您可以坚持使用一个并始终重复使用它

private PhotoCapture _photoCapture = null;
private Texture2D targetTexture = null;
private Resolution cameraResolution;
private Renderer quadRenderer;
private float dt = 0;

private void Start()
{
    cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
    var quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
    quad.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
    quadRenderer = quad.GetComponent<Renderer>();
    quadRenderer.material = new Material(Shader.Find("Unlit/Texture"));

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

    quadRenderer.material.mainTexture = targetTexture;

    quad.transform.parent = transform;
    quad.transform.localPosition = new Vector3(0.0f, 0.0f, 0.3f);

    StartCapture();
}

private void StartCapture()
{
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

private void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
    _photoCapture = captureObject;
    var cameraParameters = new CameraParameters
    {
        hologramOpacity = 0.0f,
        cameraResolutionWidth = cameraResolution.width,
        cameraResolutionHeight = cameraResolution.height,
        pixelFormat = CapturePixelFormat.BGRA32
    };

    _photoCapture.StartPhotoModeAsync(cameraParameters, OnPhotoCaptureStarted);
}

private void OnPhotoCaptureStarted(PhotoCapture.PhotoCaptureResult result)
{
    // Take the first picture
    TakePhoto();
    // or if you really want more delay
    //Invoke(nameof(TakePhoto, 3f));
}

private void TakePhoto()
{
    _photoCapture.TakePhotoAsync(OnCapturedPhotoToMemory);
}

private void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    // Don't all the time destroy and create textures
    // simply upload the new data to the already existing image
    photoCaptureFrame.UploadImageDataToTexture(targetTexture);

    Debug.Log("Captured");

    photoCaptureFrame.Dispose();

    // without the overhead of stopping and disposing etc simply take the next image
    TakePhoto();
    // or if you really want more delay
    //Invoke(nameof(TakePhoto, 3f));
}