大華攝像頭抓拍影象實時下載
阿新 • • 發佈:2021-02-04
需求:通過接入裝置後,獲取現場實時記錄。
實現:通過配置NVR,設定間隔時間定時抓拍攝像頭畫面,通過SDK定時獲取NVR對應通道的裝置抓拍圖片資料。
離線、上線、下載進度回撥。
//初始化SDK介面 m_DisConnectCallBack += new fDisConnectCallBack(DisConnectCallBack); m_ReConnectCallBack += new fHaveReConnectCallBack(ReConnectCallBack); m_DownloadPosCallBack += new fTimeDownLoadPosCallBack(DownLoadPosCallBack);
建立NVR通道實體型別
private class nvr_data { public int index { get; set; }//資料序列號 public IntPtr m_LoginID { get; set; }// public IntPtr m_DownloadID { get; set; } public string filepath { get; set; }//抓拍圖片路徑 public DateTime catchtime { get; set; }//抓拍時間 public string devicecontent { get; set; }//裝置資訊 public NET_DEVICEINFO_Ex m_DeviceInfo { get; set; } public string ip { get; set; } public string username { get; set; } public string password { get; set; } public bool download_flag { get; set; }//檢測下載狀態 public int time { get; set; }//抓拍時間間隔 public string channelanme { get; set; }//通道名稱 }
通過配置XML檔案讀取通道資訊
登入裝置開啟圖片下載執行緒
//初始化抓拍路徑 if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } //初始化SDK介面 m_DisConnectCallBack += new fDisConnectCallBack(DisConnectCallBack); m_ReConnectCallBack += new fHaveReConnectCallBack(ReConnectCallBack); m_DownloadPosCallBack += new fTimeDownLoadPosCallBack(DownLoadPosCallBack); try { NETClient.Init(m_DisConnectCallBack, IntPtr.Zero, null); NETClient.SetAutoReconnect(m_ReConnectCallBack, IntPtr.Zero); } catch (Exception ex) { this.BeginInvoke((Action<string>)setText, ex.Message); } this.BeginInvoke((Action<string>)setText, "初始化成功"); //開始初始化介面 UploadFileOss.StartUpload(); //查詢NVR配置 XmlDocument NRVconfig = new XmlDocument(); NRVconfig.Load(Application.StartupPath + "\\NRVconfig.xml"); XmlNodeList configration = NRVconfig.SelectNodes("configration"); if (configration != null && configration[0].HasChildNodes) { for (int i = 0; i < configration[0].ChildNodes.Count; i++) { XmlNode nvr = configration[0].ChildNodes[i]; //初始化資料 nvr_datas[i] = new nvr_data(); nvr_datas[i].index = i; nvr_datas[i].ip = nvr.Attributes["ip"].Value; nvr_datas[i].username = nvr.Attributes["username"].Value; nvr_datas[i].password = nvr.Attributes["password"].Value; nvr_datas[i].time = Convert.ToInt32(nvr.Attributes["time"].Value); nvr_datas[i].catchtime = DateTime.Now.AddMinutes(nvr_datas[i].time * -2 - 1); nvr_datas[i].m_LoginID = IntPtr.Zero; nvr_datas[i].m_DownloadID = IntPtr.Zero; //登入 NET_DEVICEINFO_Ex m_DeviceInfo = new NET_DEVICEINFO_Ex(); nvr_datas[i].m_LoginID = NETClient.Login(nvr_datas[i].ip, 37777, nvr_datas[i].username, nvr_datas[i].password, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref m_DeviceInfo); if (IntPtr.Zero == nvr_datas[i].m_LoginID) { this.BeginInvoke((Action<string>)setText, nvr_datas[i].ip + NETClient.GetLastError()); } else { string channelname = "通道1"; bool ret = NETClient.QueryChannelName(nvr_datas[i].m_LoginID, ref channelname); if (ret) { nvr_datas[i].channelanme = channelname; } else { this.BeginInvoke((Action<string>)setText, nvr_datas[i].ip + NETClient.GetLastError()); } this.BeginInvoke((Action<string>)setText, "LoginID" + nvr_datas[i].m_LoginID + nvr_datas[i].ip + ",37777," + nvr_datas[i].username + "," + nvr_datas[i].password + "--登入成功"); } nvr_datas[i].m_DeviceInfo = m_DeviceInfo; IntPtr pStream = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int))); NETClient.SetDeviceMode(nvr_datas[i].m_LoginID, EM_USEDEV_MODE.RECORD_STREAM_TYPE, pStream); } if (configration[0].ChildNodes.Count > 0) { //開始下載 ThreadPool.SetMaxThreads(2, 2); //從NVR資料零開始下載 th_getpic1 = new Thread(download); th_getpic1.IsBackground = true; th_getpic1.Start(0); isdownload = true; ISCatch = true; this.BeginInvoke((Action<string>)setText, "開始下載"); } }
根據NVR設定的抓拍時間間隔下載資料,防止下載到重複資料,所有通道在一個執行緒中,輪循下載。
/// <summary>
/// 下載抓拍圖片方法
/// </summary>
/// <param name="o"></param>
public void download(object o)
{
try
{
int index = Convert.ToInt32(o);
while (isdownload)
{
DateTime now = DateTime.Now;
//計算一分鐘誤差,防止方法執行的過程超過一分鐘,資料獲取不全
//time*2 ,因為DateTime end = now.AddMinutes(time * -1);nvr_datas[index].catchtime = end;
//相當於nvr_datas[index].time <= ((now.AddMinutes(time * -1) - nvr_datas[index].catchtime).Minutes - 1)
if ((nvr_datas[index].time * 2) <= ((now - nvr_datas[index].catchtime).Minutes - 1))
{
if (upload_flag)
{
IntPtr m_LoginID = nvr_datas[index].m_LoginID;
//IntPtr m_DownloadID = nvr_datas[index].m_DownloadID;
string filepath = path.TrimEnd(new char[] { '\\' }) + "\\" + nvr_datas[index].ip + now.Ticks.ToString() + ".jpg";
DateTime end = now.AddMinutes(nvr_datas[index].time * -1);//取當前時間之前time分鐘的資料
DateTime start = end.AddMinutes(nvr_datas[index].time * -1);//取結束時間之前的time分鐘資料
//停止下載
if (nvr_datas[index].m_DownloadID != IntPtr.Zero)
{
bool ret = NETClient.StopDownload(nvr_datas[index].m_DownloadID);
nvr_datas[index].m_DownloadID = IntPtr.Zero;
}
Thread.Sleep(1000);
nvr_datas[index].catchtime = end;//抓拍時間為SDK中的結束時間
nvr_datas[index].filepath = @filepath;
nvr_datas[index].devicecontent = nvr_datas[index].channelanme;//目前只取通道名稱
//開始新的下載
nvr_datas[index].m_DownloadID = NETClient.DownloadByTime(m_LoginID, 0, EM_QUERY_RECORD_TYPE.PICTURE, start, end, filepath, m_DownloadPosCallBack, IntPtr.Zero, null, IntPtr.Zero, IntPtr.Zero);
this.BeginInvoke((Action<string>)setText, "開始新的查詢 ip:" + nvr_datas[index].ip + " start:" + start.ToString("yyyy-MM-dd HH:mm:ss") + " end:" + end.ToString("yyyy-MM-dd HH:mm:ss") + "DownloadID" + nvr_datas[index].m_DownloadID);
if (IntPtr.Zero == nvr_datas[index].m_DownloadID)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
nvr_datas[index].download_flag = false;
//延時五秒校驗
Thread.Sleep(1000 * 5);
ThreadPool.QueueUserWorkItem(ISCatchPIC, index);
}
}
Thread.Sleep(1000 * 60);//一分鐘迴圈一次,預設最大下載時間為1分鐘
index = nvr_datas[index + 1] == null ? 0 : index + 1;
}
}
catch (Exception ex)
{
this.BeginInvoke((Action<string>)setText, ex.ToString() + ex.StackTrace.ToString());
}
}
nvr儲存的圖片有時幾百K,有時幾M,有時則是有圖片引數正確,但是卻不能下載,為了防止影響之後的資料下載,進行了超時校驗。
/// <summary>
/// 檢測下載狀態是否異常,異常需要重新下載
/// </summary>
/// <param name="o"></param>
private void ISCatchPIC(object o)
{
try
{
int index = Convert.ToInt32(o);
while (!nvr_datas[index].download_flag && ISCatch)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + "重新查詢圖片");
IntPtr m_LoginID = nvr_datas[index].m_LoginID;
//停止下載
if (nvr_datas[index].m_DownloadID != IntPtr.Zero)
{
bool ret = NETClient.StopDownload(nvr_datas[index].m_DownloadID);
if (!ret)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
nvr_datas[index].m_DownloadID = IntPtr.Zero;
}
bool result = NETClient.Logout(m_LoginID);
if (!result)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
Thread.Sleep(1000 * 1);
NET_DEVICEINFO_Ex m_DeviceInfo = new NET_DEVICEINFO_Ex();
nvr_datas[index].m_LoginID = NETClient.Login(nvr_datas[index].ip, 37777, nvr_datas[index].username, nvr_datas[index].password, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref m_DeviceInfo);
nvr_datas[index].m_DeviceInfo = m_DeviceInfo;
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + " 登入成功 LoginID" + nvr_datas[index].m_LoginID);
//重新開始下載
Thread.Sleep(1000);
DateTime now = DateTime.Now;
string filepath = path.TrimEnd(new char[] { '\\' }) + "\\" + now.Ticks.ToString() + ".jpg";
DateTime end = now.AddMinutes(nvr_datas[index].time * -1);//取當前時間之前time分鐘的資料
DateTime start = end.AddMinutes(nvr_datas[index].time * -1);//取結束時間之前的time分鐘資料
nvr_datas[index].catchtime = end;//抓拍時間為SDK中的結束時間
nvr_datas[index].filepath = filepath;
nvr_datas[index].m_DownloadID = NETClient.DownloadByTime(m_LoginID, 0, EM_QUERY_RECORD_TYPE.PICTURE, start, end, filepath, m_DownloadPosCallBack, IntPtr.Zero, null, IntPtr.Zero, IntPtr.Zero);
//開始新的下載
this.BeginInvoke((Action<string>)setText, "開始新的查詢 ip:" + nvr_datas[index].ip + " start:" + start.ToString("yyyy-MM-dd HH:mm:ss") + " end:" + end.ToString("yyyy-MM-dd HH:mm:ss") + "DownloadID" + nvr_datas[index].m_DownloadID);
if (IntPtr.Zero == nvr_datas[index].m_DownloadID)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
nvr_datas[index].download_flag = false;
//延時5秒校驗
Thread.Sleep(1000 * 5);
//getpic_timer = new System.Threading.Timer(new TimerCallback(download), drs[0], 1000 * 1, 1000 * 60 * time);
}
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
this.BeginInvoke((Action<string>)setText, "ThreadAbortException ");
}
catch (Exception ex)
{
this.BeginInvoke((Action<string>)setText, ex.ToString() + ex.StackTrace.ToString());
}
}
下載進度為實時監視下載過程使用,dwDownLoadSize---當次資料長度,dwDownLoadSize--資料總長度
private void DownLoadPosCallBack(IntPtr lPlayHandle, uint dwTotalSize, uint dwDownLoadSize, int index_, NET_RECORDFILE_INFO recordfileinfo, IntPtr dwUser)