CIImage 和 CIDetector 与 AVCaptureOutput 内存泄漏一起使用
CIImage and CIDetector use with AVCaptureOutput memory leak
我正在使用 CIContext、CIDetector 和 CIImage 来检测 vImage_Buffer 中的矩形,这些矩形源自 captureOutput:didOutputSampleBuffer:fromConnection 中的样本:。似乎检测器或 CIImage 正在保留内存并且无法释放。
这是有问题的代码 - 跳过此代码显示内存保持不变,否则会增加直到应用程序崩溃:
// ...rotatedBuf and format managed outside scope
// Use a CIDetector to find any potential subslices to process
CVPixelBufferRef cvBuffer;
vImageCVImageFormatRef cvFormat = vImageCVImageFormat_CreateWithCVPixelBuffer(pixelBuffer);
CVPixelBufferCreate(kCFAllocatorSystemDefault, rotatedBuf.width, rotatedBuf.height, kCVPixelFormatType_32BGRA, NULL, &cvBuffer);
CVPixelBufferLockBaseAddress(cvBuffer, kCVPixelBufferLock_ReadOnly);
err = vImageBuffer_CopyToCVPixelBuffer(&rotatedBuf, &format, cvBuffer, cvFormat, NULL, kvImageNoFlags);
CVPixelBufferUnlockBaseAddress(cvBuffer, kCVPixelBufferLock_ReadOnly);
if (![self vImageDidError:err]) {
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:cvBuffer];
NSArray *feats = [self.ciDetector featuresInImage:ciImage options:nil];
if (feats && [feats count]) {
for (CIFeature *feat in feats) {
// The frame is currently in image space, so we must convert it to a unitless space like the other rects.
CGRect frame = feat.bounds;
CGRect clip = CGRectMake(frame.origin.x / rotatedBuf.width, frame.origin.y / rotatedBuf.height,
frame.size.width / rotatedBuf.width, frame.size.height / rotatedBuf.height);
rects = [rects arrayByAddingObject:[NSValue valueWithCGRect:clip]];
}
}
}
CVPixelBufferRelease(cvBuffer);
vImageCVImageFormat_Release(cvFormat);
其他答案似乎建议在自动释放池中包装或每帧创建一个新的 CIDector,但这都不影响内存使用。
CIDetector isn't releasing memory
CIDetector won't release memory - swift
编辑:将调度队列切换到 dispatch_main_queue 以外的队列似乎已经清除了内存问题并保持 UI 响应。
我想出了一个不同的解决方案 - 在我的例子中,我 运行 在主调度队列上进行所有处理。解决这种情况的方法是为 运行 中的处理创建一个新队列。我意识到这可能是我 CPU 的大部分时间都花在调用 featuresInImage:options: 上的情况。它没有解释导致内存问题的原因,但现在我 运行 在一个单独的队列中,内存很好且恒定。
我正在使用 CIContext、CIDetector 和 CIImage 来检测 vImage_Buffer 中的矩形,这些矩形源自 captureOutput:didOutputSampleBuffer:fromConnection 中的样本:。似乎检测器或 CIImage 正在保留内存并且无法释放。 这是有问题的代码 - 跳过此代码显示内存保持不变,否则会增加直到应用程序崩溃:
// ...rotatedBuf and format managed outside scope
// Use a CIDetector to find any potential subslices to process
CVPixelBufferRef cvBuffer;
vImageCVImageFormatRef cvFormat = vImageCVImageFormat_CreateWithCVPixelBuffer(pixelBuffer);
CVPixelBufferCreate(kCFAllocatorSystemDefault, rotatedBuf.width, rotatedBuf.height, kCVPixelFormatType_32BGRA, NULL, &cvBuffer);
CVPixelBufferLockBaseAddress(cvBuffer, kCVPixelBufferLock_ReadOnly);
err = vImageBuffer_CopyToCVPixelBuffer(&rotatedBuf, &format, cvBuffer, cvFormat, NULL, kvImageNoFlags);
CVPixelBufferUnlockBaseAddress(cvBuffer, kCVPixelBufferLock_ReadOnly);
if (![self vImageDidError:err]) {
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:cvBuffer];
NSArray *feats = [self.ciDetector featuresInImage:ciImage options:nil];
if (feats && [feats count]) {
for (CIFeature *feat in feats) {
// The frame is currently in image space, so we must convert it to a unitless space like the other rects.
CGRect frame = feat.bounds;
CGRect clip = CGRectMake(frame.origin.x / rotatedBuf.width, frame.origin.y / rotatedBuf.height,
frame.size.width / rotatedBuf.width, frame.size.height / rotatedBuf.height);
rects = [rects arrayByAddingObject:[NSValue valueWithCGRect:clip]];
}
}
}
CVPixelBufferRelease(cvBuffer);
vImageCVImageFormat_Release(cvFormat);
其他答案似乎建议在自动释放池中包装或每帧创建一个新的 CIDector,但这都不影响内存使用。
CIDetector isn't releasing memory
CIDetector won't release memory - swift
编辑:将调度队列切换到 dispatch_main_queue 以外的队列似乎已经清除了内存问题并保持 UI 响应。
我想出了一个不同的解决方案 - 在我的例子中,我 运行 在主调度队列上进行所有处理。解决这种情况的方法是为 运行 中的处理创建一个新队列。我意识到这可能是我 CPU 的大部分时间都花在调用 featuresInImage:options: 上的情况。它没有解释导致内存问题的原因,但现在我 运行 在一个单独的队列中,内存很好且恒定。