我有一个问题,从我的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的bug,但每当我点击“拍摄照片”按钮时,预览窗口就会出现,它会分配内存。如果我按下“重取”,内存将被释放,但是在FinishedPiCkingMedia事件处理程序中我不能释放它。所以,在拍了几张照片之后,它就崩溃了。
任何解决方案都适合我,但如果能看到我做错了什么,那就太好了。
再次感谢您。
发布于 2012-02-01 17:20:24
这是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版本,就应该删除该解决方法,否则会泄漏缓冲区。
https://stackoverflow.com/questions/9050882
复制相似问题