Hololens 2 camera view memory leak

lin 20 Reputation points
2024-05-08T07:15:15.9433333+00:00

How do I prevent my Hololens 2 app from crashing due to memory usage when periodically capturing the camera view and displaying it on the screen? I've tried using the PhotoCapture method and WebCamTexture in Unity, but both methods cause memory usage to continuously grow until the app crashes. I'm running Holographic OS Build 22621.1272 and Unity version 2022.3.15f1. Is there a setting I'm missing or something I can do to fix this problem? I've included the code I'm using for both methods in my question.

WebCamTexture

public IEnumerator Play()
{
    yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
    if (Application.HasUserAuthorization(UserAuthorization.WebCam))
    {
        WebCamDevice[] devices = WebCamTexture.devices;
        webCamTexture = new WebCamTexture(devices[0].name, 1920, 1080, 30);
        rawImage.texture = webCamTexture;

        while (true)
        {
            webCamTexture.Play();
            yield return new WaitForSeconds(1);
            webCamTexture.Stop();
            yield return new WaitForSeconds(60);
        }
    }
}

PhotoCapture

public IEnumerator Play()
{
    while (true)
    {
        PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
        yield return new WaitForSeconds(10);
        rawImage.texture = null;
        yield return new WaitForSeconds(60);
    }
}

void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

    Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

    CameraParameters c = new CameraParameters();
    c.hologramOpacity = 0.0f;
    c.cameraResolutionWidth = 1920;
    c.cameraResolutionHeight = 1080;
    c.pixelFormat = CapturePixelFormat.BGRA32;

    captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
}
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        // Create our Texture2D for use and set the correct resolution
        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
        
        rawImage.texture = targetTexture;
    }
    // Clean up
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
    photoCaptureObject.Dispose();
    photoCaptureObject = null;
}
HoloLens Development
HoloLens Development
HoloLens: A family of Microsoft self-contained, holographic devices that enable engagement with digital content and interaction with holograms in the surrounding environment.Development: The process of researching, productizing, and refining new or existing technologies.
400 questions
{count} votes

Accepted answer
  1. Ying Li - MSFT 1,200 Reputation points Microsoft Vendor
    2024-07-16T07:33:06.3833333+00:00

     Hello, Welcome to Microsoft Q&A,

    The script of the PhotoCapture method can indeed cause a memory leak.

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

    You created new Texture2D in each iteration of the while loop. This is very expensive, and it will not be freed by Unity. You only need to create one Texture2D then re-use it. Make the targetTexture variable a global variable then initialize it once in the Start function.

    Texture2D targetTexture;
    
    // Start is called before the first frame update
    void Start()
    {
        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
    
        Coroutine coro = StartCoroutine(Play());
    }
    
    

    In the OnCapturedPhotoToMemory function, it should look something like this:

    void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
    {
    
    	if (result.success)
    	{
    	
    	    photoCaptureFrame.UploadImageDataToTexture(targetTexture);
    	    rawImage.texture = targetTexture;
    	
    	}
    // Clean up
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }
    

    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.