Reputation: 11
I tried to capture the camera view in Hololens 2 and display it on the screen of Hololens 2, but I found that it will cause the memory usage keep growing, and finally crash. enter image description here
I tried to use Photo capture method below to get the photo and set it to the texture of a raw image in Unity. https://learn.microsoft.com/en-us/windows/mixed-reality/develop/unity/locatable-camera-in-unity
And I also tried to use WebCamTexture in Unity to play and stop. https://docs.unity3d.com/ScriptReference/WebCamTexture.html
I capture the camera view once a minute, and both of the method above cause the memory usage keep growing, and finally crash.
My Holographic OS Build is 22621.1272, and my Unity version is 2022.3.15f1. Is there any setting that I'm missing or anything I can do to fix this problem?
This is the code I am using :
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;
}
Upvotes: 1
Views: 125
Reputation: 4591
When creating textures at runtime, it is your responsibility to clean them up after you are done with them. To clean up the memory used by the runtime texture, use Destroy(myTexture)
.
In the OnCapturedPhotoToMemory
function, you construct a new Texture2D from the photo capture. That texture is assigned to the raw image and then you lose reference to it.
Before assigning a new Texture2d to the raw image, first destroy the old Texture2D (if it exists). If you have a default texture assigned to the raw image, use a class variable to store the runtime texture reference and use that variable when calling Destroy.
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);
// Make sure we release the memory used by the previous generated texture
//
if (rawImage.texture) Destroy(rawImage.texture); // <- clean up memory
rawImage.texture = targetTexture;
}
Upvotes: 1