首页 文章

MJPEG over HTTP规范

提问于
浏览
1

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

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

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

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 回答

  • 2

    这在实践中似乎不是很准确 .

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

    第一帧从不包含实际图像数据 .

    是的,它确实 . 在第一个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应该如何工作 . Content-Type 标头中指定的 boundary 在实际实体流中始终以 -- 为前缀,最后一个实体之后的终止边界也以 -- 为后缀 .

    例如:

    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--
    

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

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

    处理 multipart/x-mixed-replace 时,你应该做的是:

    • 读取并丢弃HTTP响应正文,直到到达 Content-Type 响应头指定的第一个MIME边界 .

    • 然后读取MIME实体的 Headers 和数据,直到到达下一个匹配的MIME边界 .

    • 然后根据需要处理实体的数据(例如,在屏幕上显示 image/jpeg 实体) .

    • 如果连接尚未关闭,并且最后一个边界读取不是终止边界,则返回2,否则停止处理HTTP响应 .

相关问题