C# Windows窗体vs Unity3D HttpWebRequest性能

C# Windows窗体vs Unity3D HttpWebRequest性能,c#,winforms,unity3d,httpwebrequest,mjpeg,C#,Winforms,Unity3d,Httpwebrequest,Mjpeg,我正在做一个简单的程序,从一个远程IP摄像头抓取图像。经过几天的研究,我能够从MJPEG实时流中提取JPEG图像,并使用我得到的示例代码 我用Windows窗体做了一个原型。使用Windows窗体,我每10秒从IP摄像头接收80张图像 现在,我将代码移植到Unity3D,每10秒获得2帧 所以基本上大约有78张图像没有被接收到。 这东西看起来像中世纪的幻灯片放映 bool keepRunning = true; private void Decode_MJPEG_Images(strin

我正在做一个简单的程序,从一个远程IP摄像头抓取图像。经过几天的研究,我能够从MJPEG实时流中提取JPEG图像,并使用我得到的示例代码

我用Windows窗体做了一个原型。使用Windows窗体,我每10秒从IP摄像头接收80张图像

现在,我将代码移植到Unity3D,每10秒获得2帧

所以基本上大约有78张图像没有被接收到。
这东西看起来像中世纪的幻灯片放映

bool keepRunning = true;
    private void Decode_MJPEG_Images(string streamTestURL = null)
    {
        keepRunning = true;
        streamTestURL = "http://64.122.208.241:8000/axis-cgi/mjpg/video.cgi?resolution=320x240"; //For Testing purposes only

        // create HTTP request
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(streamTestURL);
        // get response
        WebResponse resp = req.GetResponse();

        System.IO.Stream imagestream = resp.GetResponseStream();

        const int BufferSize = 5000000;
        byte[] imagebuffer = new byte[BufferSize];
        int a = 2;
        int framecounter = 0;
        int startreading = 0;
        byte[] start_checker = new byte[2];
        byte[] end_checker = new byte[2];

        while (keepRunning)
        {
            start_checker[1] = (byte)imagestream.ReadByte();
            end_checker[1] = start_checker[1];

            //This if statement searches for the JPEG header, and performs the relevant operations
            if (start_checker[0] == 0xff && start_checker[1] == 0xd8)// && Reset ==0)
            {
                Array.Clear(imagebuffer, 0, imagebuffer.Length);
                //Rebuild jpeg header into imagebuffer
                imagebuffer[0] = 0xff;
                imagebuffer[1] = 0xd8;
                a = 2;
                framecounter++;
                startreading = 1;
            }

            //This if statement searches for the JPEG footer, and performs the relevant operations
            if (end_checker[0] == 0xff && end_checker[1] == 0xd9)
            {
                startreading = 0;
                //Write final part of JPEG header into imagebuffer
                imagebuffer[a] = start_checker[1];
                System.IO.MemoryStream jpegstream = new System.IO.MemoryStream(imagebuffer);

                Debug.Log("Received Full Image");
                Debug.Log(framecounter.ToString());


                //Display Image
            }

            //This if statement fills the imagebuffer, if the relevant flags are set
            if (startreading == 1 && a < BufferSize)
            {
                imagebuffer[a] = start_checker[1];
                a++;
            }

            //Catches error condition where a = buffer size - this should not happen in normal operation
            if (a == BufferSize)
            {
                a = 2;
                startreading = 0;
            }

            start_checker[0] = start_checker[1];
            end_checker[0] = end_checker[1];

        }


        resp.Close();
    }
我正在新线程中运行函数,就像在Windows窗体中一样。我最初认为Unity中的问题是因为我正在显示图像,但它不是

我删除了将图像显示为纹理的代码,并使用整数来计算接收到的图像数。尽管如此,我每10秒都会收到大约2到4张的图像。也就是说,在Windows窗体应用程序中,我每10秒就会收到大约80100的图像

Unity10秒内接收2图像是无法接受的。我写的代码似乎不是问题,因为它在Windows窗体中工作得很好

bool keepRunning = true;
    private void Decode_MJPEG_Images(string streamTestURL = null)
    {
        keepRunning = true;
        streamTestURL = "http://64.122.208.241:8000/axis-cgi/mjpg/video.cgi?resolution=320x240"; //For Testing purposes only

        // create HTTP request
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(streamTestURL);
        // get response
        WebResponse resp = req.GetResponse();

        System.IO.Stream imagestream = resp.GetResponseStream();

        const int BufferSize = 5000000;
        byte[] imagebuffer = new byte[BufferSize];
        int a = 2;
        int framecounter = 0;
        int startreading = 0;
        byte[] start_checker = new byte[2];
        byte[] end_checker = new byte[2];

        while (keepRunning)
        {
            start_checker[1] = (byte)imagestream.ReadByte();
            end_checker[1] = start_checker[1];

            //This if statement searches for the JPEG header, and performs the relevant operations
            if (start_checker[0] == 0xff && start_checker[1] == 0xd8)// && Reset ==0)
            {
                Array.Clear(imagebuffer, 0, imagebuffer.Length);
                //Rebuild jpeg header into imagebuffer
                imagebuffer[0] = 0xff;
                imagebuffer[1] = 0xd8;
                a = 2;
                framecounter++;
                startreading = 1;
            }

            //This if statement searches for the JPEG footer, and performs the relevant operations
            if (end_checker[0] == 0xff && end_checker[1] == 0xd9)
            {
                startreading = 0;
                //Write final part of JPEG header into imagebuffer
                imagebuffer[a] = start_checker[1];
                System.IO.MemoryStream jpegstream = new System.IO.MemoryStream(imagebuffer);

                Debug.Log("Received Full Image");
                Debug.Log(framecounter.ToString());


                //Display Image
            }

            //This if statement fills the imagebuffer, if the relevant flags are set
            if (startreading == 1 && a < BufferSize)
            {
                imagebuffer[a] = start_checker[1];
                a++;
            }

            //Catches error condition where a = buffer size - this should not happen in normal operation
            if (a == BufferSize)
            {
                a = 2;
                startreading = 0;
            }

            start_checker[0] = start_checker[1];
            end_checker[0] = end_checker[1];

        }


        resp.Close();
    }
我尝试过的事情

  • 我认为问题来自Unity3D编辑器运行时,所以我调用了Windows 10 64位并运行了它,但这并没有解决问题

  • 脚本后端Mono2x更改为IL2CPP,但问题仍然存在

  • Api兼容性级别.NET 2.0更改为.NET 2.0子集,但没有任何更改

  • 下面是一个有这个问题的简单函数I。它在Unity上运行得太慢,尽管我从另一个线程调用它

    bool keepRunning = true;
        private void Decode_MJPEG_Images(string streamTestURL = null)
        {
            keepRunning = true;
            streamTestURL = "http://64.122.208.241:8000/axis-cgi/mjpg/video.cgi?resolution=320x240"; //For Testing purposes only
    
            // create HTTP request
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(streamTestURL);
            // get response
            WebResponse resp = req.GetResponse();
    
            System.IO.Stream imagestream = resp.GetResponseStream();
    
            const int BufferSize = 5000000;
            byte[] imagebuffer = new byte[BufferSize];
            int a = 2;
            int framecounter = 0;
            int startreading = 0;
            byte[] start_checker = new byte[2];
            byte[] end_checker = new byte[2];
    
            while (keepRunning)
            {
                start_checker[1] = (byte)imagestream.ReadByte();
                end_checker[1] = start_checker[1];
    
                //This if statement searches for the JPEG header, and performs the relevant operations
                if (start_checker[0] == 0xff && start_checker[1] == 0xd8)// && Reset ==0)
                {
                    Array.Clear(imagebuffer, 0, imagebuffer.Length);
                    //Rebuild jpeg header into imagebuffer
                    imagebuffer[0] = 0xff;
                    imagebuffer[1] = 0xd8;
                    a = 2;
                    framecounter++;
                    startreading = 1;
                }
    
                //This if statement searches for the JPEG footer, and performs the relevant operations
                if (end_checker[0] == 0xff && end_checker[1] == 0xd9)
                {
                    startreading = 0;
                    //Write final part of JPEG header into imagebuffer
                    imagebuffer[a] = start_checker[1];
                    System.IO.MemoryStream jpegstream = new System.IO.MemoryStream(imagebuffer);
    
                    Debug.Log("Received Full Image");
                    Debug.Log(framecounter.ToString());
    
    
                    //Display Image
                }
    
                //This if statement fills the imagebuffer, if the relevant flags are set
                if (startreading == 1 && a < BufferSize)
                {
                    imagebuffer[a] = start_checker[1];
                    a++;
                }
    
                //Catches error condition where a = buffer size - this should not happen in normal operation
                if (a == BufferSize)
                {
                    a = 2;
                    startreading = 0;
                }
    
                start_checker[0] = start_checker[1];
                end_checker[0] = end_checker[1];
    
            }
    
    
            resp.Close();
        }
    
    bool-keepRunning=true;
    私有void Decode_MJPEG_图像(字符串streamTestURL=null)
    {
    保持修剪=正确;
    streamTestURL=”http://64.122.208.241:8000/axis-cgi/mjpg/video.cgi?分辨率=320x240“;//仅用于测试目的
    //创建HTTP请求
    HttpWebRequest req=(HttpWebRequest)WebRequest.Create(streamTestURL);
    //得到回应
    WebResponse resp=req.GetResponse();
    System.IO.Stream imagestream=resp.GetResponseStream();
    const int BufferSize=5000000;
    byte[]imagebuffer=新字节[BufferSize];
    INTA=2;
    int framecounter=0;
    int startreding=0;
    字节[]开始检查=新字节[2];
    字节[]结束检查程序=新字节[2];
    同时(继续修剪)
    {
    启动检查程序[1]=(字节)imagestream.ReadByte();
    结束检查程序[1]=开始检查程序[1];
    //此if语句搜索JPEG标头,并执行相关操作
    如果(启动检查程序[0]==0xff&&start检查程序[1]==0xd8)/&&Reset==0)
    {
    Array.Clear(imagebuffer,0,imagebuffer.Length);
    //将jpeg头重建到imagebuffer中
    imagebuffer[0]=0xff;
    imagebuffer[1]=0xd8;
    a=2;
    帧计数器++;
    Startreding=1;
    }
    //此if语句搜索JPEG页脚,并执行相关操作
    if(结束检查程序[0]==0xff&&end检查程序[1]==0xd9)
    {
    startreding=0;
    //将JPEG头的最后一部分写入imagebuffer
    imagebuffer[a]=启动检查程序[1];
    System.IO.MemoryStream JPEG流=新的System.IO.MemoryStream(imagebuffer);
    Log(“接收到完整映像”);
    Log(framecounter.ToString());
    //显示图像
    }
    //如果设置了相关标志,则此if语句将填充imagebuffer
    if(startreding==1&&a
    现在我把这个问题归咎于HttpWebRequest。也许它在团结中执行得很差。不确定


    发生什么事了?为什么会这样?我该如何修复它呢?

    是不是必须使用
    读取[大量]
    而不是
    读取

    阅读[很多]

    返回值类型:System.Int32读取到缓冲区的总字节数。如果有那么多字节当前不可用,则该值可以小于请求的字节数


    可以想象,
    ReadAsync
    可能会有所帮助,尽管它会产生截然不同的代码。

    对于您所说的代码的哪一部分存在性能问题,我有点困惑——是显示MPG还是您在此处发布的代码片段?假设HttpRequest不是您的问题(您可以在Fiddler中轻松测试以查看调用和获取实际需要多长时间),那么我猜您的问题在于MPG的显示,而不是您发布的代码(WinForms和Unity之间没有什么不同)

    我的猜测是,如果问题在Unity中,您是否将创建的MemoryStream传递给Unity以创建图形资源?您的代码看起来像是在读取流