我在AVCaptureSession相机中从CMSampleBuffer释放内存时遇到问题。 这是我设置捕获会话的代码。如果我处理imageDataSampleBuffer,应用程序崩溃。
using MonoTouch.CoreVideo;
using MonoTouch.CoreMedia;
using MonoTouch.AVFoundation;
using MonoTouch.ImageIO;
using MonoTouch.UIKit;
using MonoTouch.CoreFoundation;
using MonoTouch.Foundation;
using System.Drawing;
using System;
namespace myNamespace
{
public class AVFoundationCamera : UIViewController
{
public AVFoundationCamera (CameraController parView)
{
parentView = parView;
}
NSError error;
AVCaptureSession session;
AVCaptureDevice device;
AVCaptureDeviceInput input;
AVCaptureStillImageOutput output;
AVCaptureVideoPreviewLayer captureVideoPreviewLayer;
NSDictionary outputSettings;
AVCaptureConnection captureConnection;
UIButton buttCaptureImage;
public UIImageView imageV;
NSData imageData;
CameraController parentView;
public override void ViewDidAppear (bool animated)
{
base.ViewDidAppear (animated);
CreateControls();
SetupSession();
}
public override void DidReceiveMemoryWarning ()
{
imageData.Dispose();
session.Dispose();
device.Dispose();
input.Dispose();
output.Dispose();
captureVideoPreviewLayer.Dispose();
base.DidReceiveMemoryWarning ();
}
private void CreateControls()
{
imageV = new UIImageView(new RectangleF(0, 0, UIScreen.MainScreen.ApplicationFrame.Width, UIScreen.MainScreen.ApplicationFrame.Height - UIApplication.SharedApplication.StatusBarFrame.Height));
View.AddSubview(imageV);
buttCaptureImage = UIButton.FromType(UIButtonType.RoundedRect);
buttCaptureImage.Frame = new RectangleF(0, 60, 150, 30);
buttCaptureImage.SetTitle("Take a photo", UIControlState.Normal);
buttCaptureImage.TouchUpInside += HandleButtCaptureImageTouchUpInside;
View.AddSubview(buttCaptureImage);
}
void HandleButtCaptureImageTouchUpInside (object sender, EventArgs e)
{
captureConnection = null;
foreach (AVCaptureConnection capConn in output.Connections)
{
foreach (AVCaptureInputPort port in capConn.inputPorts)
{
if (port.MediaType == AVMediaType.Video)
{
captureConnection = capConn;
break;
}
}
if (captureConnection != null)
break;
}
output.CaptureStillImageAsynchronously(captureConnection, HandleAVCaptureCompletionHandlercompletionHandler);
buttCaptureImage.Enabled = false;
}
void HandleAVCaptureCompletionHandlercompletionHandler (CMSampleBuffer imageDataSampleBuffer, NSError error)
{
try
{
using (var pool = new NSAutoreleasePool ()) {
imageData = AVCaptureStillImageOutput.JpegStillToNSData(imageDataSampleBuffer);
//imageDataSampleBuffer.Dispose();
parentView.DismissModalViewControllerAnimated(true);
parentView.HandlePickedImage(imageData);
session.StopRunning();
}
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
}
private void SetupSession()
{
session = new AVCaptureSession();
session.BeginConfiguration();
session.SessionPreset = AVCaptureSession.PresetPhoto;
captureVideoPreviewLayer = new AVCaptureVideoPreviewLayer(session);
captureVideoPreviewLayer.Frame = imageV.Bounds;
imageV.Layer.AddSublayer(captureVideoPreviewLayer);
device = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video);
input = new AVCaptureDeviceInput(device, out error);
session.AddInput(input);
output = new AVCaptureStillImageOutput();
output.OutputSettings = NSDictionary.FromObjectAndKey(new NSString("AVVideoCodecKey"), new NSString("AVVideoCodecJPEG"));
session.AddOutput(output);
session.CommitConfiguration();
session.StartRunning();
}
}
}
这只是拍照的常规相机。我尝试使用你在这里发布的UIImagePickerController:https://github.com/migueldeicaza/TweetStation/blob/master/TweetStation/UI/Camera.cs消除了UIImagePickerController错误,但每当我点击“拍照”按钮时,预览窗口会显示分配内存的内容。如果我按“Retake”,正在释放内存,但在FinishedPiCkingMedia事件处理程序中我无法释放它。所以,几张照片后它崩溃了。
任何解决方案对我都有效,但看到我做错了会很棒。
再次感谢你。
答案 0 :(得分:1)
这是MonoTouch中的bug。
在获得修复之前,您可以使用一种解决方法:
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static void CFRetain (IntPtr handle);
void HandleAVCaptureCompletionHandlercompletionHandler (CMSampleBuffer imageDataSampleBuffer, NSError error)
{
try {
CFRetain (imageDataSampleBuffer.Handle);
(...)
} finally {
imageDataSampleBuffer.Dispose ();
}
}
我添加了一个Dispose调用,可能存在有限数量的缓冲区,这样就可以确保应用程序不会耗尽它们(因为GC可能需要一点时间才能自动释放它)
另请注意,一旦安装了具有真正修复的MonoTouch版本,您应该删除该解决方法,否则您将泄漏缓冲区。