c - 如何从一系列位图创建视频流并通过 IP 网络发送?

标签 c http video-streaming bare-metal

我有一个裸机应用程序运行在带有 10BASE-T 以太网 (CS8900) 的微型 16 位微 Controller ( ST10 ) 和基于 EasyWeb project 的 Tcp/IP 实现上。 .

该应用程序的主要工作是控制公共(public)交通乘客信息的 LED 矩阵显示器。它生成大约 41fps 的显示信息和可配置的显示尺寸,例如160×32 像素,1 位色深(每个 LED 可以打开或关闭)。

例子:

enter image description here

有一个微型网络服务器实现,它提供相应的帧缓冲区内容(等于 LED 矩阵显示内容)作为 PNG 或 BMP 供下载(由于 CPU 负载和 1 位颜色深度而未压缩)。所以我可以通过例如接收快照:

wget http://$IP/content.png

或者
wget http://$IP/content.bmp

或将适当的 html 代码放入 Controller 的 index.html在网络浏览器中查看。
我还可以编写 html/javascript 代码来定期更新该图片,例如每一秒,以便用户可以看到显示内容的变化。

现在进行下一步,我想以某种视频流的形式提供显示内容,然后将适当的 html 代码放入我的 index.html或者只是打开那个“流 URI”,例如vlc .

由于我的帧缓冲区位图是在未压缩的情况下构建的,因此我希望比特率恒定。

我不确定从这里开始的最佳方式是什么。

(1) 如果我已经有每帧的 PNG 格式,哪种视频格式最容易生成(但我只有几毫秒的 PNG 格式,无法缓冲更长的时间)?

请注意,我的目标系统在内存和计算能力方面都非常受资源限制。

(2) IP分发的方式有哪些?

我已经打开了一些 tcp 套接字用于监听端口 80。我可以使用分块传输编码(每个帧作为自己的块)通过 HTTP(接收后)流式传输视频。
(也许 HTTP Live Streaming 这样做?)

我也读过像 SCTP、RTP 和 RTSP 这样的想法,但在我的目标上实现它看起来需要更多的工作。由于也存在潜在的防火墙缺陷,我认为我更喜欢使用 HTTP 进行传输。

请注意,该应用程序是用纯 C 语言编写的,没有操作系统或强大的库。所有东西都是从头开始编码的,甚至是 Web 服务器和 PNG 生成。

编辑 2017-09-14,试用 APNG

正如 Nominal Animal 所建议的,我尝试使用 APNG。

我会扩展我的代码以生成合适的 fcTLfdAT每个帧的块并提供 bla.apng带有 HTTP 内容类型 image/apng .

下载那些后bla.apng它看起来很有用,例如在 Firefox 或 chrome 中打开(但不是在
konqueror ,
vlc ,
dragon player ,
gwenview )。

尝试流式传输 apng 效果很好,但只能使用 Firefox。
Chrome 想首先完全下载文件。

所以 APNG 可能是一个解决方案,但缺点是它目前只适用于 Firefox。经过进一步测试,我发现 32 位版本的 Firefox (55.0.2) 在 APNG 播放约 1 小时后崩溃,此时传输了约 100MiB 的数据。看起来他们不会丢弃旧的/过时的帧。

进一步的限制:由于 APNG 需要在每个动画块上有一个 32 位的“序列号”(每帧需要 2 个),因此可能会有最大播放持续时间的限制。但是对于我 24 毫秒的帧速率,这个持续时间限制大约是 600 天,所以我可以忍受。

请注意,APNG mime 类型是 specified by mozilla.org成为 image/apng .但是在我的测试中,我发现当我的 HTTP 服务器提供带有 Content-Type image/png 的 APNG 时,它的支持会更好一些。反而。例如。 iOS 上的 Chromium 和 Safari 将在下载后播放我的 APNG 文件(但仍不流式传输)。甚至维基百科服务器也提供例如此 beach ball APNG带有内容类型 image/png .

编辑 2017-09-17,试用动画 GIF

正如 Nominal Animal 所建议的,我现在尝试动画GIF。

完成下载(例如 100 或 1000 帧)后,在某些浏览器和查看器中看起来不错。

尝试直播在 Firefox、Chrome、Opera、Rekonq 和 Safari(在 macOS Sierra 上)中看起来没问题。
不工作 Safari(在 OSX El Capitan 和 iOS 10.3.1 上)、Konqueror、vlc、dragon player、gwenview。
例如。 Safari(在 iOS 10.3.3 和 OSX El Capitan 上测试)首先要在显示/播放之前完全下载 gif。

使用 GIF 的缺点:出于某种原因(例如 CPU 使用率),我不想对生成的帧图片进行数据压缩。例如PNG,我在 IDAT 块中使用未压缩的数据,对于具有 1Bit 颜色深度的 160x32 PNG,每帧大约有 740Byte。但是当使用 GIF without compression ,尤其是对于 1 位黑白位图,它会将像素数据放大 3-4 倍。

最佳答案

起初,嵌入式低级设备对非常复杂的现代网络浏览器不是很友好。 “连接”这些方面是非常糟糕的主意。但是,如果您的技术规范具有如此强烈的要求......

MJPEG 以流媒体视频而闻名,但在您的情况下它非常糟糕,因为它需要大量 CPU 资源并产生糟糕的压缩比和高图形质量影响。这是 jpeg 压缩的本质 - 最适合照片(具有许多渐变的图像),但不适用于像素艺术(带有清晰线条的图像)。

Looks that they don't discard old / obsolete frames.



这是正确的行为,因为这不是视频,而是动画格式并且可以重复!与 GIF 格式完全相同。 MJPEG 的情况可能会更好,因为这是作为视频流建立的。

如果我在做这个项目,我会做这样的事情:
  • 根本没有浏览器。使用winapi或一些低级库编写非常简单的 native 播放器来创建窗口,接收UDP数据包并显示二进制数据。在 Controller 部分,您只需填写 udp 数据包并将其发送给客户端。 UDP 协议(protocol)更适合实时流式传输,它在延迟的情况下丢弃数据包(帧),维护起来非常简单。
  • 使用 TCP 流式传输,但使用原始数据(每像素 1 位)。 TCP 总会产生一些延迟和缓存,你无法避免它。 和以前一样,但你不需要握手机制来启动视频流。此外,您可以使用 Flash 和 Applets 等旧的优秀技术编写您的应用程序,读取原始套接字并将您的应用程序放置在网页中。
  • 您可以尝试通过 TCP (HTTP) 传输带有原始数据的 AVI 文件。没有索引,它几乎在任何地方都无法播放,除了 VLC。奇怪的解决方案,但如果你不能编写客户端代码和魔杖 VLC - 它会起作用。
  • 您可以在中间服务器上编写转码器。例如,您的 Controller 将 UDP 数据包发送到该服务器,服务器将其转码为 h264,然后通过 RTMP 将其流式传输到 youtube...您的客户端可以使用浏览器、VLC 播放它,流质量最高可达几兆比特/秒。但是你需要一些服务器。
  • 最后,我认为这是最好的解决方案:仅向客户端发送文本、坐标、动画等,以及渲染 Controller 的所有内容。使用 Emscripten,您可以将源代码转换为 JS 并在浏览器中编写完全相同的渲染器。作为传输,您可以使用 websockets 或一些带有多个 <script> 的长 HTML 页面的技巧。元素,就像我们在过去所做的那样。

  • 请告诉我,哪个国家/城市有这个公共(public)交通乘客信息显示?它看起来很酷。在我所在的城市,每辆公共(public)汽车都已经有 LED 面板,但它只显示静态文本,很糟糕的是,没有使用这些设备的巨大潜力。

    关于c - 如何从一系列位图创建视频流并通过 IP 网络发送?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46141993/

    相关文章:

    c++ - Gcc 中是否有命令来获取关键字(或函数等)的描述?

    http - 在哪里可以找到所有浏览器的默认超时设置?

    java - 用 Java 发送 40(ish) HTTP 请求的最快方法是什么?

    opencv - 显示 UDP 组播 Rawvideo 流

    c++ - void *function() 是指向函数的指针还是返回 void* 的函数?

    c++ - C/C++ linux fork() 和 exec()

    php - cURL 输出中的 "local_ip"和 "primary_ip"是什么意思?

    internet-explorer - JW Player 未向 Internet Explorer 用户显示

    video - 我需要服务器端视频流吗?

    c++ - 如何以编程方式缓慢移动窗口,就好像用户正在做一样?