2012-01-29 2 views
1

У меня проблема с выпуском памяти из CMSampleBuffer в моей камере AVCaptureSession. Это мой код для установки сеанса захвата. Если я удалю imageDataSampleBuffer, приложение отключится.AVCaptureSession CMSampleBuffer issue

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 я не могу ее освободить. Итак, после нескольких фотографий он падает.

Любое решение работает для меня, но было бы здорово увидеть, что я делаю неправильно.

Еще раз спасибо.

+1

Просьба заполнить полный образец кода –

+0

Приложите его к отчету об ошибке на странице http://bugzilla.xamarin.com и дайте нам ссылку на этот вопрос. благодаря! – poupou

ответ

1

Это был bug в MonoTouch.

Существует обходной путь, вы можете использовать, пока вы не получите исправление:

[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 с реальным исправлением, так как вы будете буферов в противном случае.

 Смежные вопросы

  • Нет связанных вопросов^_^