【问题标题】:PhotoCaputure causes memory leak in UnityPhotoCaputure 导致 Unity 中的内存泄漏
【发布时间】:2021-11-12 01:33:28
【问题描述】:

我正在使用 unity 的 Photocapture Object 拍摄带有 hololens 的视频。 我根据官方的示例代码写了代码,但是我在更新函数中改变了过程,以获取多张图片而不是一张。

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

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

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();
        }

    }



}

【问题讨论】:

    标签: c# unity3d out-of-memory hololens


    【解决方案1】:

    我很确定您也希望/必须处理 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));
    }
    

    【讨论】:

    • 谢谢,我尝试添加 photoCaptureFrame.Dispose();但它仍然会泄漏内存。
    • @lain 这是你的全部代码吗?你到底在用捕获的图像做什么?因为目前您的代码根本没有显示...您只是将帧捕获到内存...但是为了什么?
    • @lain 你也说the unity profiler does not show any gradual increase in memory usage after the code is executed ...那你怎么知道有内存泄漏?我无法使用答案底部的代码重现这一点......我只删除了在前一个完成之前尝试开始的照片捕获引起的错误
    • 省略了其余代码以澄清问题。我的整个代码在以下链接上。我计划将照片发送到服务器进行 AI 处理,但我目前处于可视化阶段。 github.com/pacifinapacific/MR_sample/blob/main/PhotocapW.cs
    • 为什么总是破坏和创造一个新的纹理?只需创建一次并使用 photoCaptureFrame.UploadImageDataToTexture(targetTexture); 将其更新为相同的纹理
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2015-07-06
    • 2014-06-07
    • 2013-11-20
    • 2011-10-28
    • 2016-01-18
    • 2012-12-13
    相关资源
    最近更新 更多