Форма Windows vs Unity3D HttpWebRequest Performace

Я работаю над простой программой, которая захватывает изображение с удаленной IP-камеры. После нескольких дней исследований я смог извлечь JPEG- изображения из прямой трансляции MJPEG с помощью полученных образцов кодов.

Я сделал прототип с использованием Windows Form. С Windows Form я получаю соответственно 80 изображений каждые 10 секунд с IP-камеры.

Теперь я перенес код на Unity3D и получаю около 2 кадров каждые 10 секунд.

Так что в основном около 78 изображений не получены. Это похоже на средневековое слайд-шоу PowerPoint.

Я запускаю функцию в новом потоке так же, как я делал в форме Windows. Сначала я подумал, что проблема в Unity заключается в том, что я отображал изображение, но это не так.

Я удалил код, который отображает изображение в качестве текстуры и использовал целое число для подсчета количества полученных изображений. Тем не менее, я получаю от 2 до 4 изображений каждые 10 секунд. То есть в приложении Windows Form я получаю от 80 до 100 изображений каждые 10 секунд.

Получение 2 изображений за 10 секунд в Unity неприемлемо для того, что я делаю. Код, который я написал, похоже, не является проблемой, потому что он прекрасно работает в Windows Form.

Вещи, которые я пробовал:

  1. Я думал, что проблема в среде Unity3D Editor, поэтому я вызвал Windows 10 64bit и запустил ее, но это не решило проблему.

  2. Изменен сервер сценариев с Mono2x на IL2CPP, но проблема все еще остается.

  3. Уровень совместимости Api изменен с .NET 2.0 на .NET 2.0 Subset и ничего не изменилось.

Ниже приведена простая функция 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();
    }

Теперь я обвиняю HttpWebRequest в этой проблеме. Возможно, это было плохо реализовано в Unity. Точно сказать не могу....

В чем дело? Почему это происходит? Как я могу это исправить?

2 ответа

Решение

Возможно, это тот случай, когда нужно использовать Read[a lot] вместо Read??

Read[a lot]:

https://msdn.microsoft.com/en-us/library/system.io.stream.read(v=vs.110).aspx

Возвращаемое значение Тип: System.Int32 Общее количество байтов, считанных в буфер. Это может быть меньше количества запрошенных байтов, если столько байтов в данный момент недоступно

Предположительно, ReadAsync может помочь, руководство, хотя это приводит к совершенно другому коду.

Я немного озадачен тем, какая часть вашего кода, о которой вы говорите, имеет проблему с производительностью - она ​​отображает MPG или это фрагмент кода, который вы опубликовали здесь? Предполагая, что HttpRequest не является вашей проблемой (которую вы можете легко протестировать в Fiddler, чтобы увидеть, сколько времени на самом деле занимают вызов и выборка), тогда я предполагаю, что ваша проблема заключается в отображении MPG, а не кода, который вы опубликовали (который не будет отличаться между WinForms и Unity)

Я думаю, если проблема в Unity, вы передаете созданный MemoryStream в Unity для создания графического ресурса? Ваш код выглядит так, как будто он читает поток, и когда он достигает символа конца изображения, он создает новый MemoryStream, который содержит все содержимое буфера данных. Это может быть проблемой для Unity, которая не является проблемой в WinForms - поток памяти, кажется, содержит весь созданный вами буфер, но это больше, чем фактический контент, который вы прочитали - возможно, Unity видит это как поврежденный Jpg?

Попробуйте использовать конструктор MemoryStream, который берет диапазон байтов от вашего байта [] и передает только те данные, которые, как вы знаете, составляют ваш поток изображений.

Другие проблемы в коде могут быть (но вряд ли связаны с производительностью); Фрагментация кучи больших объектов при создании и отбрасывании большого байта []; нединамическое хранение входящего потока (фиксированный размер буфера назначения); нет проверки размера входящего потока или индикаторов окончания потока (если поток ответа не содержит весь поток изображения, кажется, что стратегии для этого нет).

Другие вопросы по тегам