Frage

Ich versuche, eine IP-Kamera-Anwendung für das iPhone mit Mono Touch zu erstellen. Um die Kamera-Feed zu erhalten, rufe ich die CGImage.ScreenImage Verfahren kontinuierlich und wandeln das resultierende UIImage in einen Byte-Array, das dann über an den Browser gesendet wird. Der Kamera-Feed angezeigt eine UIImagePickerController-Klasse durch die

Einstellung
SourceType = UIImagePickerControllerSourceType.Camera;

Hier sind der vollständige Code für die ImageController Klasse:

public class ImageController : UIImagePickerController
{
    private HttpListener listener;

    public ImageController ()
    {
        SourceType = UIImagePickerControllerSourceType.Camera;
        start();
    }

    void start()
    {
        listener = new HttpListener();
        listener.Prefixes.Add( "http://+:8001/" );
        listener.Prefixes.Add( "http://+:8001/current.jpg/" );
        listener.Start();
        listener.BeginGetContext( HandleRequest, listener );
    }

    public override void DidReceiveMemoryWarning ()
    {
        GC.Collect();
    }


    private void HandleRequest(IAsyncResult result)
    {
        HttpListenerContext context = listener.EndGetContext( result );
        listener.BeginGetContext( HandleRequest, listener );
        if ( context.Request.RawUrl.Contains( "current.jpg" ) )
        {
            context.Response.StatusCode = (int) HttpStatusCode.OK;
            context.Response.ContentType = @"multipart/x-mixed-replace;boundary=--myboundary";
            context.Response.KeepAlive = true;
            byte [] imageData;
            byte [] boundary;

            while ( true )
            {
                imageData = worker();
                boundary =
                    Encoding.UTF8.GetBytes(
                        "\r\n--myboundary\r\nContent-Type: image/jpeg\r\nContent-Length: " +
                        imageData.Length + "\r\n\r\n" );
                context.Response.OutputStream.Write( boundary, 0, boundary.Length );
                context.Response.OutputStream.Write( imageData, 0, imageData.Length );
                imageData = null;
                boundary = null;
            }
        }
        else
        {
            string responseString = @"<html xmlns=""http://www.w3.org/1999/xhtml""> <body bgcolor=""#fffffff"">"+
                        @"<img name=""current"" src=""current.jpg"" border=""0"" id=""current"" /></body></html>";

            byte [] responseByte = Encoding.UTF8.GetBytes( responseString );
            context.Response.ContentType = "text/html";
            context.Response.KeepAlive = true;
            context.Response.StatusCode = (int) HttpStatusCode.OK;
            context.Response.ContentLength64 = responseByte.Length;
            context.Response.OutputStream.Write( responseByte, 0, responseByte.Length );
            context.Response.OutputStream.Close();
         }
     }

     private byte [] worker()
     {
         byte [] imageArray;
         using ( var screenImage = CGImage.ScreenImage )
         {
             using ( var image = UIImage.FromImage(screenImage) )
             {
                 using ( NSData imageData = image.AsJPEG())
                 {
                     imageArray = new byte[imageData.Length];
                     Marshal.Copy(imageData.Bytes, imageArray, 0, Convert.ToInt32(imageData.Length));
                 }
             }
         }
         return imageArray;
      }
   }
}

Das Problem, das ich habe ist, dass ich eine Speicher Warnung nach etwa 20 Sekunden von Streaming und eine zweite nach 5 Sekunden empfangen, dann die Anwendung abstürzt.

2010-11-08 13: 12: 56,457 MonoTouchCGImageScreenImageTest [2251: 307] Received Speicher Warnung. Level = 1

2010-11-08 13: 13: 11,059 MonoTouchCGImageScreenImageTest [2251: 307] Received Speicher Warnung. Level = 2

Alle Bilder, die in der Anweisung using entsorgt und die imagedata Variable wird auch auf null gesetzt worden sind wurden angezeigt worden, wenn es übertragen wird. Gibt es eine Methode, die aufgerufen werden muss, oder gibt es eine bessere Lösung für mein Problem? Jede mögliche Hilfe würde geschätzt.

Danke

War es hilfreich?

Lösung

Sie rufen Arbeiter () in einer nicht enden wollenden Schleife:

        while ( true )
        {
            imageData = worker();
            boundary =
                Encoding.UTF8.GetBytes(
                    "\r\n--myboundary\r\nContent-Type: image/jpeg\r\nContent-Length: " +
                    imageData.Length + "\r\n\r\n" );
            context.Response.OutputStream.Write( boundary, 0, boundary.Length );
            context.Response.OutputStream.Write( imageData, 0, imageData.Length );
            imageData = null;
            boundary = null;
        }

Das bedeutet, dass auch tho Sie entsorgen, Sie in einem engen Zuordnungsschleife sind, die eine Menge Druck auf die GC stellen wird.

Zusätzlich Sie verwenden UIImage.FromImage (), die von der obj-c ein Autoreleased Objekt zurückgibt Laufzeit, aber da Sie nie in der Hauptschleife ergeben, kann die NSAutoreleasePool diese Aufgabe nicht lösen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top