Windows Phone通过UDP提供的摄像头信息“非常糟糕”.缓慢

本文关键字:非常 非常糟糕 缓慢 信息 摄像头 通过 Phone UDP Windows | 更新日期: 2023-09-27 17:50:48

我一直在做一个私人项目,我想学习如何在windows手机上编程,在某一点上,我开始摆弄插座和相机,一个伟大的想法出现在我的脑海中视频输入(愚蠢的我甚至尝试)。

但现在我在这里,我有一些东西好吧,它工作起来像一个魅力,但Lumia 800不能快速通过for循环。它每7-8秒发送一帧我觉得很奇怪,因为它应该足够强大。感觉和看起来就像在56k调制解调器上看色情片,没有色情片。

我还意识到一帧是317000像素,每帧大约1MB,我还发送xy坐标,所以我的每帧占用2.3MB,我仍然在用不同的方法来解决这个问题,以保持它的低。所以我猜我需要做圆顶魔法,使位置和像素值都是一个可接受的大小。因为如果我以一个可接受的速度启动它,至少需要60MB/s才能达到30fps,但这是另一天的问题。

//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. 找到明显的问题(谷歌和朋友的好主意,这就是为什么我在这里)

Windows Phone通过UDP提供的摄像头信息“非常糟糕”.缓慢

问题几乎肯定是数据的混乱。将1兆字节的二进制数据转换为数兆字节的文本,然后提取和发送单个字符将增加每字节源数据的巨大开销。循环遍历单个像素来构建发送缓冲区将占用(相对而言)地质时间尺度。

要做到这一点,最快的方法可能是从相机抓取二进制数据的缓冲区,并发送它与一个UDP写。只有在必要时才处理或分解手机上的数据,并且要小心直接访问原始二进制数据-不要将其全部转换为字符串再转换回二进制。添加到此进程中的每个额外方法调用只会增加开销。如果您必须使用循环,请尝试在循环之外尽可能多地预先计算,以尽量减少每次迭代所做的工作。

需要注意以下几点:#1将原始图像数组分解成多个片段,然后通过网络发送。不确定Linq是否在Windows Phone上可用,但类似于此。由于处理时间和内存使用,从intstring再到byte的转换效率非常低。更好的方法是将int数组的块直接批量复制到byte数组。示例