Как создать видеопоток из серии растровых изображений и отправить его по IP-сети?

У меня есть приложение с белым металлом, работающее на крошечном 16-битном микроконтроллере (ST10) с 10BASE-T Ethernet (CS8900) и реализация Tcp/IP на основе проекта EasyWeb.

Основной задачей приложения является управление дисплеем со светодиодной матрицей для информации о пассажирском движении. Он генерирует информацию отображения примерно со скоростью 41fps и настраиваемый размер дисплея, например. 160 × 32 пикселя, глубина цвета 1 бит (каждый светодиод может быть либо включен, либо выключен).

Пример:

введите описание изображения здесь

Реализован крошечный веб-сервер, который обеспечивает соответствующий контент буфера кадров (равный содержимому отображаемого матричного дисплея) в качестве PNG или BMP для загрузки (как несжатых из-за нагрузки процессора, так и глубины цвета 1 бит). Поэтому я могу получать моментальные снимки, например:

wget http://$IP/content.png

или

wget http://$IP/content.bmp

или поместите соответствующий html-код в контроллер index.html, чтобы просмотреть его в веб-браузере. Я также мог написать html/javascript код для обновления этого изображения периодически, например. каждую секунду, чтобы пользователь мог видеть изменения отображаемого содержимого.

Теперь для следующего шага я хочу предоставить отображаемый контент как некоторый поток видео, а затем поместить соответствующий html-код в мой index.html или просто открыть этот "потоковый URI", например. vlc.

Поскольку мои растровые изображения framebuffer создаются несжатыми, я ожидаю постоянный битрейт.

Я не уверен, как лучше всего начать с этого.

(1) Какой видеоформат легче всего сгенерировать, если у меня уже есть PNG для каждого фрейма (но у меня есть этот PNG только на пару миллисекунд и вы не можете его долгое время буферизовать)?

Обратите внимание, что моя целевая система очень ограничена ресурсами как в памяти, так и в вычислительной мощности.

(2) Каким образом для распределения по IP?

У меня уже есть несколько сокетов tcp, открытых для прослушивания на порту 80. Я мог бы транслировать видео через HTTP (после получения) с помощью кодированной передачи передачи (каждый кадр как собственный фрагмент). (Возможно, HTTP Live Streaming, как это?)

Я бы также читал о таких, как SCTP, RTP и RTSP, но это похоже на работу по реализации этого на моей цели. И поскольку есть также потенциальный недостаток firewall, я думаю, что предпочитаю HTTP для транспорта.

Обратите внимание, что приложение закодировано в простой C, без операционной системы или мощных библиотек. Все материалы кодируются с нуля, даже с веб-сервером и генерацией PNG.

Редактировать 2017-09-14, попробовать с APNG

Как было предложено Номинальным животным, я попытался использовать APNG.

Я бы расширил свой код, чтобы создать соответствующие фрагменты fcTL и fdAT для каждого фрейма и предоставить bla.apng HTTP Content-Type image/apng.

После загрузки этих bla.apng он выглядит полезным, когда, например, открытие в firefox или chrome (но не в konqueror, vlc, игрок-дракон, gwenview).

Попытка потока, что apng работает красиво, но только с firefox. Chrome хочет сначала загрузить файл полностью.

Таким образом, APNG может быть решением, но с недостатком, что он в настоящее время работает только с firefox. После дальнейших испытаний я узнал, что 32-битные версии Firefox (55.0.2), сбойные после примерно 1 часа воспроизведения APNG, были переданы за 100 Мбайт данных за это время. Похоже, что они не отбрасывают старые/устаревшие кадры.

Дополнительные ограничения: поскольку APNG должен иметь 32-битный "порядковый номер" в каждом фрагменте анимации (требуется 2 для каждого кадра), может быть ограничение максимальной продолжительности воспроизведения. Но для моей частоты кадров 24 мс этот предел длительности составляет около 600 дней, и поэтому я мог бы жить с.

Обратите внимание, что тип mime APNG был указанный mozilla.org, как image/apng. Но в моих тестах я узнал, что он немного лучше поддерживается, когда мой HTTP-сервер поставляет APNG с Content-Type image/png. Например. Chromium и Safari на iOS будут воспроизводить мои APNG файлы после загрузки (но все еще не потоковые). Даже сервер wikipedia обеспечивает, например, этот пляжный мяч APNG с Content-Type image/png.

Изменить 2017-09-17, попробовать с анимированным GIF

Как также предлагается Номинальное животное, Я теперь попробовал анимированный GIF.

Выглядит хорошо в некоторых браузерах и зрителях после полной загрузки (например, 100 или 1000 кадров).

Попытка трансляции в реальном времени выглядит нормально в Firefox, Chrome, Opera, Rekonq и Safari (на macOS Sierra). Не работает Safari (на OSX El Capitan и iOS 10.3.1), Konqueror, vlc, игрок-дракон, gwenview. Например. Safari (проверенный на iOS 10.3.3 и OSX El Capitan) сначала хочет полностью загрузить gif перед отображением/воспроизведением.

Недостаток использования GIF: по какой-либо причине (например, использование процессора) я не хочу реализовывать сжатие данных для созданных изображений фреймов. Напр. PNG, я использую несжатые данные в блоке IDAT и для 160x32 PNG с глубиной цвета 1Bit a получил около 740 бит для каждого кадра. Но при использовании GIF без сжатия, особенно для 1 бит черно-белых растровых изображений, он сбрасывает пиксельные данные в 3-4 раза.

Ответ 1

Сначала встроенные низкоуровневые устройства не очень дружелюбны с очень сложными современными веб-браузерами. Это очень плохая идея "соединить" такие стороны. Но если у вас есть техническая спецификация с этими сильными требованиями...

MJPEG хорошо известна для потокового видео, но в вашем случае это очень плохо, так как требует много ресурсов ЦП и создает плохую степень сжатия и высокое качество изображения. Это характер сжатия jpeg - лучше всего с фотографиями (изображения со многими градиентами), но плохо с пиксельным искусством (изображения с резкими линиями).

Похоже, что они не отбрасывают старые/устаревшие кадры.

И это правильное поведение, поскольку это не видео, а формат анимации и может быть повторен! Точно так же будет и в формате GIF. Случай с MJPEG может быть лучше, поскольку это установлено как видеопоток.

Если бы я выполнял этот проект, я бы сделал что-то вроде этого:

  • Нет обозревателя AT ALL. Напишите очень простой родной плеер с winapi или некоторой низкоуровневой библиотекой, чтобы просто создать окно, получить UDP-пакет и отобразить двоичные данные. В части контроллера вы должны просто заполнить udp-пакеты и отправить их клиенту. Протокол UDP лучше для потоковой передачи в реальном времени, он отбрасывает пакеты (кадры) в случае задержки, очень прост в обслуживании.

  • Поток с TCP, но исходные данные (1 бит на пиксель). TCP всегда будет производить некоторую задержку и кеширование, вы не можете избежать этого. То же, что и раньше, но вам не нужен механизм установления связи для запуска видеопотока. Кроме того, вы можете написать свое приложение на старых хороших технологиях, таких как Flash и Applets, прочитать сырой сокет и разместить свое приложение на веб-странице.

  • Вы можете попытаться передать файлы AVI с необработанными данными через TCP (HTTP). Без индексов он будет воспроизводиться почти везде, кроме VLC. Странное решение, но если вы не можете написать код клиента и палочку VLC - он будет работать.

  • Вы можете писать транскодер на промежуточном сервере. Например, ваш контроллер отправил UDP-пакеты на этот сервер, сервер перекодировал его в h264 и потоки через RTMP на youtube... Ваши клиенты могут воспроизводить его с помощью браузеров, VLC, поток будет в хорошем качестве до нескольких мбит/с. Но вам нужен сервер.

  • И, наконец, я думаю, что это лучшее решение: отправлять клиенту только текст, координаты, анимацию и т.д., все, что делает ваш контроллер. С Emscripten вы можете конвертировать ваши источники в JS и записывать один и тот же рендерер в браузере. В качестве транспорта вы можете использовать websockets или некоторые трюки с длинномерной HTML-страницей с несколькими элементами <script>, как в прошлые годы.

Скажите, пожалуйста, в какой стране/городе есть этот информационный показ пассажира для общественного транспорта? Это выглядит очень круто. В моем городе каждый автобус уже имеет светодиодную панель, но он просто показывает статический текст, это просто ужасно, что огромный потенциал устройств не используется.

Ответ 2

Вы пробовали просто прокладывать это через websocket и обрабатывать двоичные данные в javascript?

Каждый отправленный фрейм веб-камеры будет соответствовать кадру вашей анимации.

вы должны взять эти данные и нарисовать их в html-холсте. Это будет работать в каждом браузере с поддержкой websocket - что будет довольно много - и даст вам всю необходимую гибкость. (и плеер может быть более высоким, чем "кодер" во встроенном устройстве)