监控摄像机(海康、大华等)内部带的录像功能一般录制的是h264文件,这种文件格式简单的把每一帧h264字节数据保存到文件里。

实际使用中,可能需要对特定录像进行反复检测,以训练、改进视频检测算法的准确性。

这里介绍两种方法。

1.使用RTSP流

服务端1:live555 使用C++代码开发容易些,网上代码较多

服务端2:vlc播放器,参考 使用vlc播放器做rtsp服务器

客户端:使用vlc播放器播放rtsp视频

使用vlc进行二次开发做自己的播放器

web网页中使用vlc插件播放相机rtsp流视频

Emgu.CV 播放视频-本地文件/RTSP流

2.自定义格式

使用UDP数据包

服务端针对.h264视频一帧帧发送给客户端,使用UDP协议

h264帧,尤其是I帧大小可能超过64K,即udp数据包的上限,需要考虑分包

分包:可以在第一字节=0表示不分包,=1表示分包这是第一包,=2这是第二包

视频清晰度暂定为480P,此时P帧一般小于64k,而I帧部分大于64k。这样可以不考虑数据包会先发后到导致乱序

客户端:

示例代码如下

IPEndPoint ipep = new IPEndPoint(IPAddress.Any, );
udpsockVideo = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpsockVideo.ReceiveBufferSize = ;
try
{
//绑定网络地址
udpsockVideo.Bind(ipep); IPAddress ip = IPAddress.Any; //得到客户机IP
IPEndPoint sender = new IPEndPoint(ip, );
EndPoint Remote = (EndPoint)(sender); log.ErrorFormat("udp开始接收视频帧"); bool bIframe = false;
unAvailableCnt = ;
while (!bAbortvehicleEventThread)
{
if (udpsockVideo == null)
{
log.ErrorFormat("udp接收视频帧 Socket 为空!");
return;
} if (udpsockVideo.Available <= )
{
unAvailableCnt++;
if (unAvailableCnt > )
{
log.ErrorFormat("udp接收视频帧:连续未接收到视频"); //实际比10秒多
unAvailableCnt = ;
}
//TimeSpan ts = new TimeSpan(100000);//0.1毫秒 1 ticks =十亿分之一秒 百万分之一毫秒 千分之一微秒,1纳秒
Thread.Sleep(); //sleep 1时,由于精度问题,经常耗时10-16毫秒
continue;
} byte[] data = new byte[];
int recv = udpsockVideo.Receive(data);
if (recv < )
{
continue;
} if (ip != IPAddress.Any && (Remote as IPEndPoint).Address.ToString().Trim() != ip.ToString().Trim())
{
continue;
} unAvailableCnt = ; try
{
if (data[] != 0x00)
{
bIframe = true; byte b = data[];
if (b == 0x01)
{
iframe1 = new byte[recv - ];
Array.Copy(data, , iframe1, , recv - );
}
log.ErrorFormat(b.ToString());
if (b == 0x02)
{
iframe2 = new byte[recv - ];
Array.Copy(data, , iframe2, , recv - );
log.ErrorFormat(iframe2.Length.ToString());
} if (iframe1.Length < && iframe2.Length < )
{
int iframeLen = iframe1.Length + iframe2.Length; byte[] Iframe = new byte[iframeLen];
Array.Copy(iframe1, , Iframe, , iframe1.Length);
Array.Copy(iframe2, , Iframe, iframe1.Length, iframe2.Length); DecH264Frame(Iframe); iframe1 = new byte[];
iframe2 = new byte[];
bIframe = false;
}
}
else
{
if (bIframe)
{
bIframe = false;
iframe1 = new byte[];
iframe2 = new byte[];
} byte[] frame = new byte[recv - ];
Array.Copy(data, , frame, , recv - );
DecH264Frame(frame);
}
}
catch (System.Exception ex)
{
log.ErrorFormat("udp接收视频帧 解码/录像出错:" + ex.Message);
} }
}
catch (Exception e)
{
log.ErrorFormat("udp接收视频帧出错。端口:{0},出错信息:{1}", , e.Message);
}
finally
{
if (udpsockVideo != null)
{
udpsockVideo.Close();
}
}

最新文章

  1. android 史上最简单易懂的跨进程通讯(Messenger)!
  2. 重新用delphi7写东西
  3. Html网页使用jQuery传递参数并获取Web API的数据
  4. 69道Spring面试题和答案
  5. BootStrap安装
  6. 013--VS2013 C++ 地图贴图-其它格式图片
  7. 性能测试指标&amp;说明 [解释的灰常清楚哦!!]
  8. 进程控制之wait和waitpid函数
  9. Hadoop2安装
  10. POJ 3660 Cow Contest (Floyd)
  11. 没用调用flush导致的数据保存丢失
  12. 【Java基础】Java中的多态
  13. [译]Stairway to Integration Services Level 10 - 高级事件活动
  14. 学习css之文本属性
  15. 去除url后缀(.html,.jsp等)的有效方法
  16. EJB通过注解方式注入并使用其他EJB或者服务、配置JBoss数据源
  17. 【一天一道LeetCode】#219. Contains Duplicate II
  18. eclipse详细安装教程与环境变量设置
  19. 第六节:详细讲解Java中的装箱与拆箱及其字符串
  20. Laravel框架中的event事件操作

热门文章

  1. SQL Sever AlwaysOn的数据同步原理
  2. vue(2)—— vue简单语法运用,常用指令集
  3. C#学习笔记---C#操作SQL数据库
  4. AngularJS学习之旅—AngularJS 服务(八)
  5. linux内核IDR机制详解【转】
  6. 报错:library not found for -lstdc++.6.0.9
  7. 理解ECS的概念和Unity中的ECS设计
  8. Thinkphp volist 多重循环原样输出数组key值的使用总结
  9. SQLServer之索引简介
  10. LeetCode算法题-Reverse String II(Java实现)