首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVCaptureSession CMSampleBuffer问题

AVCaptureSession CMSampleBuffer问题
EN

Stack Overflow用户
提问于 2012-01-29 12:13:56
回答 1查看 1.9K关注 0票数 1

我有一个问题,从我的AVCaptureSession相机的CMSampleBuffer释放内存。这是我设置捕获会话的代码。如果我处理imageDataSampleBuffer,应用程序就会崩溃。

代码语言:javascript
复制
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事件处理程序中我不能释放它。所以,在拍了几张照片之后,它就崩溃了。

任何解决方案都适合我,但如果能看到我做错了什么,那就太好了。

再次感谢您。

EN

回答 1

Stack Overflow用户

发布于 2012-02-01 17:20:24

这是MonoTouch中的一个bug

在获得修复之前,您可以使用以下解决方法:

代码语言:javascript
复制
[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版本,就应该删除该解决方法,否则会泄漏缓冲区。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9050882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档