Как создать видеопоток из серии растровых изображений и отправить его по 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 - что будет довольно много - и даст вам всю необходимую гибкость. (и плеер может быть более высоким, чем "кодер" во встроенном устройстве)