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个解决方案
接受失败(但这不会发生,所以让我们看看2)
减少发送的数据量(破坏质量640x480是足够小的我认为)
找到明显的问题(谷歌和朋友的好主意,这就是为什么我在这里)
问题几乎肯定是数据的混乱。将1兆字节的二进制数据转换为数兆字节的文本,然后提取和发送单个字符将增加每字节源数据的巨大开销。循环遍历单个像素来构建发送缓冲区将占用(相对而言)地质时间尺度。
要做到这一点,最快的方法可能是从相机抓取二进制数据的缓冲区,并发送它与一个UDP写。只有在必要时才处理或分解手机上的数据,并且要小心直接访问原始二进制数据-不要将其全部转换为字符串再转换回二进制。添加到此进程中的每个额外方法调用只会增加开销。如果您必须使用循环,请尝试在循环之外尽可能多地预先计算,以尽量减少每次迭代所做的工作。需要注意以下几点:#1将原始图像数组分解成多个片段,然后通过网络发送。不确定Linq是否在Windows Phone上可用,但类似于此。由于处理时间和内存使用,从int
到string
再到byte
的转换效率非常低。更好的方法是将int
数组的块直接批量复制到byte
数组。示例