-
Notifications
You must be signed in to change notification settings - Fork 178
Description
I’m facing an issue with OpenCV for Unity v2.6.5 where calling videoWriter.release() on iOS causes the app to crash with this error:
-[NSAutoreleasePool retain]: Cannot retain an autorelease pool
I’ve tried moving .release() to OnDisable(), adding a delay, and ensuring videoWriter is properly initialized — but no luck so far. Interestingly, the same setup worked perfectly fine in OpenCV v2.5.9.
I’m currently using Unity 2022.3.59f1. Any ideas on what could be causing this or how to fix it?
`using System.Collections;
using System.Collections.Generic;
using System.IO;
using OpenCVForUnity.CoreModule;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.UnityUtils.Helper;
using OpenCVForUnity.VideoioModule;
using UnityEngine;
namespace Utilities
{
[RequireComponent(typeof(WebCamTexture2MatHelper))]
public class OpenCVCameraRecorder : MonoBehaviourInstance
{
#region PrivateVariables
/// <summary>
/// The webcam texture to mat helper.
/// </summary>
private WebCamTexture2MatHelper webCamTextureToMatHelper;
/// <summary>
/// The bgr mat.
/// </summary>
private Mat bgrMat;
private VideoWriter videoWriter;
private bool isRecording = false;
// Path to save recording
private string fileSavePath = null;
#endregion /PrivateVariables
#region UnityMethods
private void OnEnable()
{
GameConstants.IsFaceRecordingConsentGiven = true;
}
private void Start()
{
if (!GameConstants.IsFaceRecordingConsentGiven)
{
return;
}
webCamTextureToMatHelper = gameObject.GetComponent<WebCamTexture2MatHelper>();
webCamTextureToMatHelper.Initialize();
webCamTextureToMatHelper.onInitialized.AddListener(OnWebCamTextureToMatHelperInitialized);
webCamTextureToMatHelper.onDisposed.AddListener(OnWebCamTextureToMatHelperDisposed);
webCamTextureToMatHelper.onErrorOccurred.AddListener(OnWebCamTextureToMatHelperErrorOccurred);
}
private void OnDisable()
{
if (!GameConstants.IsFaceRecordingConsentGiven)
{
return;
}
if (webCamTextureToMatHelper != null)
{
webCamTextureToMatHelper.Dispose();
}
if (isRecording)
{
isRecording = false;
videoWriter?.Dispose();
videoWriter = null;
}
}
private void Update()
{
if (!GameConstants.IsFaceRecordingConsentGiven)
{
return;
}
if (isRecording && webCamTextureToMatHelper.IsPlaying() && webCamTextureToMatHelper.DidUpdateThisFrame())
{
Mat matFrame = webCamTextureToMatHelper.GetMat();
Imgproc.cvtColor(matFrame, bgrMat, Imgproc.COLOR_RGBA2BGR);
videoWriter.write(bgrMat);
}
}
#endregion /UnityMethods
#region WebCamTexture2MatHelperCallback
public void OnWebCamTextureToMatHelperInitialized()
{
Mat webCamTextureMat = webCamTextureToMatHelper.GetMat();
bgrMat = new Mat(webCamTextureMat.rows(), webCamTextureMat.cols(), CvType.CV_8UC3);
Debug.Log("WebCamTextureToMatHelperInitialized");
}
public void OnWebCamTextureToMatHelperDisposed()
{
bgrMat?.Dispose();
}
public void OnWebCamTextureToMatHelperErrorOccurred(Source2MatHelperErrorCode errorCode, string message)
{
Debug.LogError($"WebCamTextureToMatHelperErrorOccurred: {errorCode}, {message}");
}
#endregion /WebCamTexture2MatHelperCallback
#region PublicMethods
public void StartRecording(string filePath)
{
if (!GameConstants.IsFaceRecordingConsentGiven)
{
return;
}
if (isRecording)
{
Debug.LogWarning("Recording is already in progress.");
return;
}
if (bgrMat == null || bgrMat.empty())
{
Debug.LogError("Frame size is invalid. Ensure bgrMat is properly initialized before starting recording.");
return;
}
fileSavePath = filePath;
if (File.Exists(fileSavePath))
{
Debug.LogWarning($"File already exists at path: {fileSavePath}. Deleting existing file.");
File.Delete(fileSavePath);
}
// Get frame properties
int frameWidth = bgrMat.width();
int frameHeight = bgrMat.height();
double fps = webCamTextureToMatHelper.GetFPS();
// Create new VideoWriter each time
videoWriter = new VideoWriter();
int fourcc = VideoWriter.fourcc('H', '2', '6', '4');
videoWriter.open(fileSavePath, fourcc, fps, new Size(frameWidth, frameHeight));
if (!videoWriter.isOpened())
{
Debug.LogError("Failed to open VideoWriter.");
videoWriter.release();
return;
}
isRecording = true;
}
public void StopRecording()
{
if (!GameConstants.IsFaceRecordingConsentGiven)
{
return;
}
if (!isRecording)
{
Debug.LogWarning("Recording is not in progress.");
return;
}
isRecording = false;
// Release synchronously
if (videoWriter != null && !videoWriter.IsDisposed)
{
try
{
videoWriter.release();
}
catch (System.Exception ex)
{
Debug.LogError("Error releasing VideoWriter: " + ex.Message);
}
}
}
#endregion /PublicMethods
}
}
`