有个需求是要把某杂牌 IP 摄像头的图像实时采集到 C# Winform 上。打开 Wireshark,登录上摄像头提供的网页后台,当视频开始播放后,可以抓到 RTSP 的视频流地址。

Wireshark抓包

有了 RTSP 视频流,引入 C# 的常见方法是使用 VLC 的 SDK 或者 RTSPClientSharp,再在视频流里截取图像。一开始我用的是 VLC SDK,但是无论我怎么配置 VLC 的参数,视频流的延迟总会有半秒到一秒左右,而摄像头网页后台显示的视频流延迟很低,估计最大不超过 200ms,但并未提供截图相关的 HTTP 接口,仅提供了 OCX 控件的截图接口。

有点头痛,因为这个需求要求实时性比较高,延迟一秒是无法接受的,而我对处理流这块可以说一窍不通。一筹莫展之际,突然想到 OCX 是可以当成 Winform 的控件的。于是把安装在电脑上的 ocx 控件找到,拖入 VS 的工具箱中,再把控件拖到窗体上,是一个黑色的框,估计这个就是显示视频流的最终控件了。

OCX-and-VS

在对象浏览器中找到对应的类,可以看到其导出方法,其中 CapturePicture、Login 和 OpenVideo 应该就是我所需要的方法了。

OCX-Method.png

登录网页后台,F12 呼出控制台窗口,查找一下关键的 js 代码:

js1.png

Login 方法,和对象浏览器中的

public virtual int Login(
    string iPAddr, 
    int port, 
    string name, 
    string psw, 
    int sync, 
    int timeout
)

参数匹配,查看 cookie 可以得到相应参数的值,iPAddr、name、psw 根据实际情况获取,port、sync 和 timeout 分别为固定值 8080、0 和 5000。故在 C# 里 Login 的相应代码就是

控件名.Login("192.168.2.201", 8080, "username", "password", 0, 5000);

值得吐槽的一点是:访问 554 端口的 RTSP 流是不需要用户密码的,但使用 OCX 控件却需要😥。

OCX 控件提供了登录状态的回调:CallBackLoginState,其 Event 结构如下:

CallBackLoginStateEvent

结合 js 代码,可知 loginState0 时登录成功。带 Right 的参数盲猜和权限有关,reserved 不清楚,也不关心。

js2

登录完成后就可以 OpenVideoCapturePicture 了。

SB