MJPEG over HTTP规范

时间:2017-12-09 15:09:36

标签: http jpeg specifications mjpeg

我试图创建一个工具来从通过http传输的mjpeg流中获取帧。我没有找到任何规范,所以我查看了维基百科所说的here

  

响应对MJPEG文件或流的GET请求,服务器   通过HTTP流式传输JPEG帧序列。一种特殊的哑剧型   内容类型multipart/x-mixed-replace;boundary=<boundary-name>   通知客户端期望几个部分(帧)作为答案   由<boundary-name>分隔。这个边界名称是明确的   在MIME类型声明中公开。

但这在实践中似乎并不准确。我倾倒了一些流来了解它们的行为方式。大多数流具有以下格式(其中CRLF是回车换行符,部分标题是一些没有状态行的标题字段):

Status line (e.g. HTTP/1.0 200 OK) CRLF
Header fields (e.g. Cache-Control: no-cache) CRLF
Content-Type header field (e.g. Content-Type: multipart/x-mixed-replace; boundary=--myboundary) CRLF
CRLF (Denotes that the header is over)
Boundary (Denotes that the first frame is over) CRLF
Partial header fields (mostly: Content-type: image/jpeg) CRLF
CRLF (Denotes that this "partial header" is over)
Actual frame data CRLF
(Sometimes here is an optional CRLF)
Boundary
Starting again at partial header (line 6)

第一帧从不包含实际图像数据。 所有分析的流都具有Content-Type标头,类型设置为multipart/x-mixed-replace

但是有些流在这里弄错了:

两台服务器声称boundary="MOBOTIX_Fast_Serverpush",但之后使用--MOBOTIX_Fast_Serverpush作为帧分隔符。

这让我非常恼火,所以我想采用另一种方法来获取帧。

由于每个JPEG都以0xFF 0xD8作为图像起点标记开始,以0xFF 0xD9结束,我可以开始寻找这些。这似乎是一种非常肮脏的方法,我不是很喜欢它,但它可能是最强大的方法。

在我开始实现之前,我是否有一些关于MJPEG通过HTTP错过的观点?是否有通过HTTP传输MJPEG的真实规范? 只是观察JPEG的开始和结束标记而不是使用边界来分隔帧时有什么注意事项?

1 个答案:

答案 0 :(得分:6)

  

这在实践中似乎并不准确。

在实践中非常准确。你只是没有正确处理它。

  

第一帧从未包含实际图像数据。

是的,确实如此。在第一个MIME实体之前总是一个起始边界(因为MIME可以在第一个实体之前包含序言数据)。您认为MIME边界仅存在于每个MIME实体之后,但事实并非如此。

我建议您阅读MIME规范,尤其是RFC 2045RFC 2046。 MIME在这种情况下工作正常,你只是没有正确地解释结果。

  

实际帧数据CRLF
  (有时这里是可选的CRLF)
  边界

实际上,最后一个CRLF不是可选的,它实际上是跟随MIME实体数据的下一个边界的一部分(参见RFC 2046 Section 5)。 MIME边界必须出现在它们自己的行上,因此在实体数据之后人为地插入CRLF,这对于不是由它们自己的CRLF自然终止的数据类型(如图像)尤其重要。

  

两台服务器声明了boundary="MOBOTIX_Fast_Serverpush",但之后使用--MOBOTIX_Fast_Serverpush作为帧分隔符

这就是假设的MIME工作原理。 boundary标头中指定的Content-Type 始终在实际实体流中以--为前缀,最后一个实体后面的终止边界也以{为后缀{1}}也是。

例如:

--
  

这让我非常恼火,所以我想采用另一种方法来获取帧。

你所想的不会起作用,也不像你想的那么强大。您确实需要正确处理MIME流。

处理Content-Type: multipart/x-mixed-replace; boundary="MOBOTIX_Fast_Serverpush" --MOBOTIX_Fast_Serverpush Content-Type: image/jpeg <jpeg bytes> --MOBOTIX_Fast_Serverpush Content-Type: image/jpeg <jpeg bytes> --MOBOTIX_Fast_Serverpush ... and so on ... --MOBOTIX_Fast_Serverpush-- 时,您应该做的是:

  1. 读取并丢弃HTTP响应正文,直到您到达multipart/x-mixed-replace响应标头指定的第一个MIME边界。
  2. 然后读取MIME实体的标题和数据,直到到达下一个匹配的MIME边界。
  3. 然后根据需要处理实体的数据(例如,在屏幕上显示Content-Type实体)。
  4. 如果连接尚未关闭,并且最后一个边界读取不是终止边界,请返回2,否则停止处理HTTP响应。