大华摄像头直连政府服务器,本来有个叫dss的app可以连接到服务器 播放监控,现在需要接入到我们系统里来,询问大华开发人员以后居然发现不支持网页端,
我们的pc端和app 是浏览器嵌套的网页,后面想了一种方案 我再服务器写一个控制台程序 内嵌一个http服务器 控制台程序是可以tcp的 直播流通过tcp发送过来 然后 等待 app pc来http获取。
直播我选择了 http-flv的方式 特点是 延迟低
流媒体协议 RTMP, HTTP-FLV, HLS 简单对比
前端使用 flv.js 来播放
由于一般的 http都是一问一答 请求完毕,而直播流不同 需要一直串流,也就是一直回复。只需要在 回复的header里Content-Length 去掉 不通知 浏览器 body的长度 浏览器就不会主动断开连接
同时需要加上 跨域
e.Response.ContentType = "video/x-p2p";
e.Response.Headers.Set("Connection", "keep-alive");
e.Response.Headers.Set("Access-Control-Allow-Origin", "*");
e.Response.Headers.Set("Access-Control-Allow-Methods", "GET, POST");
e.Response.Headers.Set("Access-Control-Allow-Credentials", "true");
下面是sdk的代码
IntPtr result1 = DPSDK_Create(dpsdk_sdk_type_e.DPSDK_CORE_SDK_SERVER, ref nPDLLHandle);//创建sdk实例
IntPtr result = DPSDK_Login(nPDLLHandle, ref loginInfo, (IntPtr)10000); 登录账号密码
IntPtr result = DPSDK_GetRealStreamEx(nPDLLHandle, out realseq, ref Info, dpsdk_stream_convertor_type_e.DPSDK_CORE_SC_FLV_STREAM, fMediaData, IntPtr.Zero); 获取大华设备flv格式流 注意 回调函数的委托 不能让托管垃圾回收了
ok 准备就绪
用vlc 测试工具 播放 卡了30秒左右播放成功。然后 去 flv.js 测试网站上播放失败了 测试地址是 http://bilibili.github.io/flv.js/demo/
flv报了一个 不是完整的包的提示。
然后我用vlc 控制台测试 提示
然后我拿着这串文字去 bing 搜索到 ffmepg的源码 阅读源码以后发现 AMF2的数据包 地址 不完整
flv文件流格式 https://blog.csdn.net/mm792261167/article/details/69396493 这位说的很清楚
然后 在程序里截取sdk返回的第一段数据流,通过逐字节分析 发现 AMF2 指定后续有13个属性实际只有11个 并且在数据中居然 多出来 9个0x00 分析过程被我误删了这里一笔带过 。
修复代码如下,因为头的字节都是固定的所以我直接绝对索引修复
private byte[] RefashAMF(byte[] bufHandle)
{
bufHandle[16] = (byte)(bufHandle[16] - 9);
bufHandle[41] = 0x0b;
bufHandle[277] = 0x00;
bufHandle[278] = 0xfd;
byte[] data = new byte[bufHandle.Length - 9];
Array.Copy(bufHandle, 0, data, 0, 211);
Array.Copy(bufHandle, 220, data, 211, bufHandle.Length - 220);
return data;
}
修正直播流以后 发现vlc 能正常播放并且 vlc的控制台也没有报错了。flv.js 测试发现 没有报错但是也无法播放。
后面找到flv.js的源码开始调试发现视频中没有音频 他就不播放,这个设计也是有点坑,大华的sdk也是有点坑 我再sdk上设置了获取音频视频的混合流 结果只返回了 视频。
flv.js的配置需要设置成 这样就可以播放了。测试 vlc 和flv.js都可以正常播放.因为是直播可能多人同时观看同一个流 我刚开始是想 一个视频接收 多http转发,后面发现 第二个人无法播放
我在返回里给第二个人加上视频头以后,发现有画面但是会卡住 等几十秒就是正常播放,客户肯定是不想卡住的 然后就同一个视频开多个sdk实例去接收视频流 这样内存占用大 但是不会出现卡住的问题。
最后说实话我估计大华自己都没有测试过自己的视频流是否是正确的 pc和app都是直接调用的另一个方式 是大华的私有协议 直接传显示控件的句柄进去,这种获取公开视频流方式 居然视频流中存在错误数据,在公司分析sdk返回的第一个包3w多字节
眼已花 眼睛度数+100. 希望能帮到后面的人