Domanda

Sto cercando di creare un'applicazione telecamera IP per iPhone utilizzando mono tocco. Per ottenere il feed fotocamera, che io chiamo il metodo CGImage.ScreenImage continuo e convertire l'UIImage risultante in un array di byte, che viene poi trasmesso attraverso il browser. L'alimentazione della fotocamera viene visualizzato con una classe UIImagePickerController impostando il

SourceType = UIImagePickerControllerSourceType.Camera;

Ecco il codice completo per la classe ImageController:

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;
      }
   }
}

Il problema che sto avendo è che ricevo un avviso di memoria dopo circa 20 secondi di streaming e un secondo dopo 5 secondi, quindi l'applicazione si blocca.

2010-11-08 13: 12: 56,457 MonoTouchCGImageScreenImageTest [2251: 307] avviso di memoria Ricevuto. Livello = 1

2010-11-08 13: 13: 11,059 MonoTouchCGImageScreenImageTest [2251: 307] avviso di memoria Ricevuto. Livello 2 =

Tutte le immagini che sono stati visualizzati sono stati eliminati nel using e la variabile imageData è stato anche insieme ad nullo una volta che è trasmesso. C'è qualche metodo che deve essere chiamato o c'è una soluzione migliore per il mio problema? Qualsiasi aiuto sarebbe apprezzato.

Grazie

È stato utile?

Soluzione

che si sta chiamando lavoratore () in un ciclo senza fine:

        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;
        }

Il che significa che anche tho Prima di gettare, sei in un ciclo di assegnazione stretto che metterà un sacco di pressione sul GC.

Inoltre, si sta utilizzando UIImage.FromImage (), che restituisce un oggetto autoreleased dal obj-c runtime, ma dal momento che non cedere ai ciclo principale, il NSAutoreleasePool non si può rilasciare questo oggetto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top