監控攝像機(海康、大華等)內部帶的錄像功能一般錄制的是h264文件,這種文件格式簡單的把每一幀h264字節數據保存到文件里。
實際使用中,可能需要對特定錄像進行反復檢測,以訓練、改進視頻檢測算法的准確性。
這里介紹兩種方法。
1.使用RTSP流
服務端1:live555 使用C++代碼開發容易些,網上代碼較多
服務端2:vlc播放器,參考 使用vlc播放器做rtsp服務器
客戶端:使用vlc播放器播放rtsp視頻
2.自定義格式
使用UDP數據包
服務端針對.h264視頻一幀幀發送給客戶端,使用UDP協議
h264幀,尤其是I幀大小可能超過64K,即udp數據包的上限,需要考慮分包
分包:可以在第一字節=0表示不分包,=1表示分包這是第一包,=2這是第二包
視頻清晰度暫定為480P,此時P幀一般小於64k,而I幀部分大於64k。這樣可以不考慮數據包會先發后到導致亂序
客戶端:
示例代碼如下
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 6000); udpsockVideo = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); udpsockVideo.ReceiveBufferSize = 1000000; try { //綁定網絡地址 udpsockVideo.Bind(ipep); IPAddress ip = IPAddress.Any; //得到客戶機IP IPEndPoint sender = new IPEndPoint(ip, 0); EndPoint Remote = (EndPoint)(sender); log.ErrorFormat("udp開始接收視頻幀"); bool bIframe = false; unAvailableCnt = 0; while (!bAbortvehicleEventThread) { if (udpsockVideo == null) { log.ErrorFormat("udp接收視頻幀 Socket 為空!"); return; } if (udpsockVideo.Available <= 0) { unAvailableCnt++; if (unAvailableCnt > 10000) { log.ErrorFormat("udp接收視頻幀:連續未接收到視頻"); //實際比10秒多 unAvailableCnt = 0; } //TimeSpan ts = new TimeSpan(100000);//0.1毫秒 1 ticks =十億分之一秒 百萬分之一毫秒 千分之一微秒,1納秒 Thread.Sleep(1); //sleep 1時,由於精度問題,經常耗時10-16毫秒 continue; } byte[] data = new byte[100000]; int recv = udpsockVideo.Receive(data); if (recv < 4) { continue; } if (ip != IPAddress.Any && (Remote as IPEndPoint).Address.ToString().Trim() != ip.ToString().Trim()) { continue; } unAvailableCnt = 0; try { if (data[0] != 0x00) { bIframe = true; byte b = data[0]; if (b == 0x01) { iframe1 = new byte[recv - 2]; Array.Copy(data, 2, iframe1, 0, recv - 2); } log.ErrorFormat(b.ToString()); if (b == 0x02) { iframe2 = new byte[recv - 1]; Array.Copy(data, 1, iframe2, 0, recv - 1); log.ErrorFormat(iframe2.Length.ToString()); } if (iframe1.Length < 100000 && iframe2.Length < 100000) { int iframeLen = iframe1.Length + iframe2.Length; byte[] Iframe = new byte[iframeLen]; Array.Copy(iframe1, 0, Iframe, 0, iframe1.Length); Array.Copy(iframe2, 0, Iframe, iframe1.Length, iframe2.Length); DecH264Frame(Iframe); iframe1 = new byte[100000]; iframe2 = new byte[100000]; bIframe = false; } } else { if (bIframe) { bIframe = false; iframe1 = new byte[100000]; iframe2 = new byte[100000]; } byte[] frame = new byte[recv - 1]; Array.Copy(data, 1, frame, 0, recv - 1); DecH264Frame(frame); } } catch (System.Exception ex) { log.ErrorFormat("udp接收視頻幀 解碼/錄像出錯:" + ex.Message); } } } catch (Exception e) { log.ErrorFormat("udp接收視頻幀出錯。端口:{0},出錯信息:{1}", 6000, e.Message); } finally { if (udpsockVideo != null) { udpsockVideo.Close(); } }