5

私はWindowsPhoneでプログラミングする方法を学びたいというプライベートプロジェクトに取り組んでおり、ある時点でソケットとカメラをいじり始め、ビデオフィードを思いついたのです(私は試してみることさえできませんでした) )。

しかし今、私はここにいます。それは魅力のように機能しますが、Lumia800はforループを十分に速く通過することができません。それは、7〜8秒ごとにフレームを送信します。それは、十分に強いはずなので、奇妙だと思います。ポルノなしで56kモデムでポルノを見ているように感じ、見えます。

また、フレームが317000ピクセルであり、合計でフレームあたり約1MBになることにも気付きました。また、xy座標を送信しているので、フレームあたり2.3MBを使用しますが、これを抑えるために別の方法で解決しています。ですから、位置とピクセルの両方の値を許容可能なサイズにするために、ドームマジックを行う必要があると思います。atmは許容可能な速度でそれを取得するので、30fpsのようなものを取得するには少なくとも60MB /秒が必要ですが、それは別の日の問題です。

//How many pixels to send per burst (1000 seems to be the best)
    const int PixelPerSend = 1000;
    int bSize = 7 * PixelPerSend;
    //Comunication thread UDP feed   
    private void EthernetComUDP() //Runs in own thread
    {
        //Connect to Server
        clientUDP = new SocketClientUDP();
        int[] ImageContent = new int[(int)cam.PreviewResolution.Height *   (int)cam.PreviewResolution.Width];
        byte[] PacketContent = new byte[bSize];
        string Pixel,l;
        while (SendingData)
        {
            cam.GetPreviewBufferArgb32(ImageContent);
            int x = 1, y = 1, SenderCount = 0;
            //In dire need of a speedup
            for (int a = 0; a < ImageContent.Length; a++) //this loop
            {
                Pixel = Convert.ToString(ImageContent[a], 2).PadLeft(32, '0');

                //A - removed to conserve bandwidth
                //PacketContent[SenderCount] = Convert.ToByte(Pixel.Substring(0, 8), 2);//0
                //R
                PacketContent[SenderCount] = Convert.ToByte(Pixel.Substring(8, 8), 2);//8
                //G
                PacketContent[SenderCount + 1] = Convert.ToByte(Pixel.Substring(16, 8), 2);//16
                //B
                PacketContent[SenderCount + 2] = Convert.ToByte(Pixel.Substring(24, 8), 2);//24

                //Coordinates
                //X
                l = Convert.ToString(x, 2).PadLeft(16, '0');
                //X bit(1-8)
                PacketContent[SenderCount + 3] = Convert.ToByte(l.Substring(0, 8), 2);
                //X bit(9-16)
                PacketContent[SenderCount + 4] = Convert.ToByte(l.Substring(8, 8), 2);

                //Y
                l = Convert.ToString(y, 2).PadLeft(16, '0');
                //Y bit(1-8)
                PacketContent[SenderCount + 5] = Convert.ToByte(l.Substring(0, 8), 2);
                //Y bit(9-16)
                PacketContent[SenderCount + 6] = Convert.ToByte(l.Substring(8, 8), 2);

                x++;
                if (x == cam.PreviewResolution.Width)
                {
                    y++;
                    x = 1;
                }

                SenderCount += 7;
                if (SenderCount == bSize)
                {
                    clientUDP.Send(ConnectToIP, PORT + 1, PacketContent);
                    SenderCount = 0;
                }
            }
        }
        //Close on finish
        clientUDP.Close();
    }

私は簡単にするために、ピクセルを個別に使用して送信しようとしました

BitConverter.GetBytes(ImageContent[a]);

私が作成した文字列解析の混乱の代わりに(修正するには概念実証が必要でした)、単純なBitConverterを実行してもそれほど高速化されませんでした。

だから今、私の最後のアイデアで、UDP送信者ソケットの魔女はmsdnのライブラリのものとほぼ同じです。

    public string Send(string serverName, int portNumber, byte[] payload)
    {
        string response = "Operation Timeout";
        // We are re-using the _socket object that was initialized in the Connect method
        if (_socket != null)
        {
            // Create SocketAsyncEventArgs context object
            SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
            // Set properties on context object
            socketEventArg.RemoteEndPoint = new DnsEndPoint(serverName, portNumber);
            // Inline event handler for the Completed event.
            // Note: This event handler was implemented inline in order to make this method self-contained.
            socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
            {
                response = e.SocketError.ToString();
                // Unblock the UI thread
                _clientDone.Set();
            });
            socketEventArg.SetBuffer(payload, 0, payload.Length);
            // Sets the state of the event to nonsignaled, causing threads to block
            _clientDone.Reset();
            // Make an asynchronous Send request over the socket
            _socket.SendToAsync(socketEventArg);
            // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
            // If no response comes back within this time then proceed
            _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
        }
        else
        {
            response = "Socket is not initialized";
        }
        return response;
    }

全体として、私は3つの解決策に行き着きました

  1. 敗北を受け入れる(しかし、それは起こらないので、2を見てみましょう)

  2. 送信されるデータの量を減らします(破壊品質640x480は十分に小さいと思います)

  3. 明らかな問題を見つけてください(グーグルと友人は良いアイデアを使い果たしました、それが私がここにいる理由です)

4

2 に答える 2

2

問題はほぼ間違いなくデータをいじることです。メガバイトのバイナリデータを数メガバイトのテキストに変換してから、個々の文字を抽出して送信すると、ソースデータのバイトあたりのオーバーヘッドが大幅に増加します。個々のピクセルをループして送信バッファーを構築するには、(比較的)地質学的なタイムスケールが必要です。

これを行う最も速い方法は、カメラからバイナリデータのバッファを取得し、1回のUDP書き込みで送信することです。必要な場合にのみ、電話でデータを処理または分割し、元のバイナリデータに直接アクセスするように注意してください。すべてを文字列に変換してバイナリに戻さないでください。このプロセスに追加するメソッド呼び出しはすべて、オーバーヘッドを追加するだけです。ループを使用する必要がある場合は、ループの外側でできる限り事前に計算して、各反復で実行される作業を最小限に抑えるようにしてください。

于 2013-01-07T00:03:34.617 に答える
0

いくつかのことが頭に浮かびます。#1生の画像配列を細かく分割してネットワーク経由で送信します。LinqがWindowsPhoneで利用できるかどうかはわかりませんが、このようなものです。
#2からへの変換はint、処理時間とメモリ使用量のために非常に非効率的です。より良いアプローチは、配列のチャンクを配列に直接一括コピーすることです。stringbyteintbyte

于 2013-01-06T22:59:56.567 に答える