hkcamera.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. #include "hkcamera.h"
  2. #include "./ui_hkcamera.h"
  3. #include <QDebug>
  4. #include <QDateTime>
  5. #include <QFile>
  6. #include <QFileInfo>
  7. // #include <QMediaPlayer>
  8. // #include <QVideoWidget>
  9. // #include <QMediaPlaylist>
  10. #include <QVBoxLayout>
  11. // #include "VideoPlayer.h"
  12. LONG m_playPort; /* 全局的播放库port号 */
  13. HKCamera::HKCamera(QObject *parent)
  14. : QObject(parent)
  15. // , ui(new Ui::HKCamera)
  16. {
  17. // ui->setupUi(this);
  18. m_logger = spdlog::get("HK_Camera");
  19. if(m_logger == nullptr)
  20. {
  21. qDebug() << "获取HK_Camera logger失败!";
  22. return;
  23. }
  24. /* 初始化变量 */
  25. m_playPort = -1;
  26. // m_vLayout = new QVBoxLayout(this);
  27. SPDLOG_LOGGER_INFO(m_logger,"============ Hello HK_Camera ============");
  28. }
  29. HKCamera::~HKCamera()
  30. {
  31. // delete ui;
  32. /* 退出登录 */
  33. NET_DVR_Logout(m_loginID);
  34. /* 释放SDK资源,重复清除资源会怎么样 */
  35. NET_DVR_Cleanup();
  36. }
  37. /* 初始化海康摄像头SDK */
  38. bool HKCamera::initHKCamera(const HKLoginInfo& info)
  39. {
  40. /* 初始化海康摄像头SDK */
  41. if(!NET_DVR_Init())
  42. {
  43. SPDLOG_LOGGER_ERROR(m_logger,"NET_DVR_Init 失败!");
  44. return false;
  45. }
  46. /* 设置超时时间 */
  47. NET_DVR_SetConnectTime(3000,3);
  48. NET_DVR_SetReconnect();
  49. /* 设置异常消息回调函数 */
  50. #ifdef Q_OS_LINUX
  51. NET_DVR_SetExceptionCallBack_V30(0, nullptr, exceptionCallBack, nullptr);
  52. #endif
  53. /* 用户登录,同步登陆 */
  54. NET_DVR_USER_LOGIN_INFO loginInfo = {0};
  55. /* 返回的设备信息,包括序列号、设备类型、通道号等 */
  56. NET_DVR_DEVICEINFO_V40 deviceInfo = {0};
  57. strncpy(loginInfo.sDeviceAddress, info.HostName.toStdString().c_str(), info.HostName.count());
  58. strncpy(loginInfo.sUserName, info.UserName.toStdString().c_str(), info.UserName.count());
  59. strncpy(loginInfo.sPassword, info.Password.toStdString().c_str(), info.Password.count());
  60. loginInfo.wPort = info.Port; /* 端口 */
  61. loginInfo.bUseAsynLogin = 0; /* 同步登陆,= 1 是异步登录 */
  62. SPDLOG_DEBUG("登录信息:{}:{}:{}:{}",loginInfo.sDeviceAddress,loginInfo.wPort, loginInfo.sUserName, loginInfo.sPassword);
  63. /* 这里是同步登陆,返回值就是设备操作ID,异步登录需要在回调函数中取出返回的ID */
  64. m_loginID = NET_DVR_Login_V40(&loginInfo, &deviceInfo);
  65. if(m_loginID < 0)
  66. {
  67. SPDLOG_LOGGER_ERROR(m_logger,"登录摄像机 {} 失败,错误代码:{}",info.HostName.toStdString(),NET_DVR_GetLastError());
  68. NET_DVR_Cleanup(); /* 需不需要在这里清除资源? */
  69. return false;
  70. }
  71. /* 取出通道号 */
  72. m_devInfo.AChannelNum = 0;
  73. m_devInfo.AChannelStart = 0;
  74. m_devInfo.DChannelNum = 0;
  75. m_devInfo.DChannelStart = 0;
  76. m_devInfo.AChannelNum = deviceInfo.struDeviceV30.byChanNum; /* 模拟通道个数 */
  77. m_devInfo.AChannelStart = deviceInfo.struDeviceV30.byStartChan; /* 模拟通道的起始通道号 */
  78. unsigned char h8 = deviceInfo.struDeviceV30.byIPChanNum; /* 数字通道的最大个数需要组合起来 */
  79. unsigned char l8 = deviceInfo.struDeviceV30.byHighDChanNum;
  80. m_devInfo.DChannelNum = h8 * 256 + l8;
  81. m_devInfo.DChannelStart = deviceInfo.struDeviceV30.byStartDChan;/* 数字通道起始号 */
  82. SPDLOG_LOGGER_TRACE(m_logger,"最大模拟通道号数:{},起始号:{}",m_devInfo.AChannelNum,m_devInfo.AChannelStart);
  83. SPDLOG_LOGGER_TRACE(m_logger,"最大数字通道号数:{},起始号:{}",m_devInfo.DChannelNum,m_devInfo.DChannelStart);
  84. SPDLOG_LOGGER_INFO(m_logger,"****** HK SDK初始化完成! ******");
  85. return true;
  86. }
  87. /* 获取模拟通道数 */
  88. quint32 HKCamera::getAnalogChannelNum()
  89. {
  90. return m_devInfo.AChannelNum;
  91. }
  92. /* 获取模拟通道起始号 */
  93. quint32 HKCamera::getAnalogChannelStart()
  94. {
  95. return m_devInfo.AChannelStart;
  96. }
  97. /* 获取数字通道数 */
  98. quint32 HKCamera::getDigitalChannelNum()
  99. {
  100. return m_devInfo.DChannelNum;
  101. }
  102. /* 获取数字通道起始号 */
  103. quint32 HKCamera::getDigitalChannelSatrt()
  104. {
  105. return m_devInfo.DChannelStart;
  106. }
  107. /**
  108. * @brief 实时播放监控,视频流在回调函数中
  109. *
  110. * @param Channel
  111. * @return true
  112. * @return false
  113. */
  114. bool HKCamera::getRealDataFromCamera(int Channel)
  115. {
  116. /* 启动预览并设置回调数据流 */
  117. LONG realPlayHandle;
  118. NET_DVR_PREVIEWINFO playInfo = {0};
  119. playInfo.hPlayWnd = 0; //需要SDK解码时句柄设为有效值,仅取流不解码时可设为空
  120. playInfo.lChannel = Channel; //预览通道号
  121. playInfo.dwStreamType = 0; //0-主码流,1-子码流,2-码流3,3-码流4,以此类推
  122. playInfo.dwLinkMode = 0; //0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
  123. playInfo.bBlocked = 1; //0- 非阻塞取流,1- 阻塞取流
  124. /* 设置回调函数 */
  125. realPlayHandle = NET_DVR_RealPlay_V40(m_loginID, &playInfo, realDataCallBack, nullptr);
  126. if (realPlayHandle < 0)
  127. {
  128. SPDLOG_ERROR("NET_DVR_RealPlay_V40()调用错误,错误代码:{}",NET_DVR_GetLastError());
  129. return false;
  130. }
  131. /* 延时一定时间,这里延时也可以使用一个条件变量,在另一个线程控制通断 */
  132. std::this_thread::sleep_for(std::chrono::seconds(10));
  133. //关闭预览
  134. NET_DVR_StopRealPlay(realPlayHandle);
  135. SPDLOG_LOGGER_DEBUG(m_logger,"实时获取数据结束");
  136. return true;
  137. }
  138. /**
  139. * @brief 实时显示视频,使用SDK解码
  140. *
  141. * @param Chnannel
  142. * @param playWindow
  143. */
  144. void HKCamera::realPlayBack(int channel, QWidget* playWindow)
  145. {
  146. // if(playWindow == nullptr)
  147. // {
  148. // SPDLOG_LOGGER_ERROR(m_logger,"播放窗口错误!");
  149. // return;
  150. // }
  151. /* 启动预览并设置回调数据流 */
  152. LONG realPlayHandle;
  153. NET_DVR_PREVIEWINFO playInfo = {0};
  154. playInfo.hPlayWnd = 0; //需要SDK解码时句柄设为有效值,仅取流不解码时可设为空
  155. playInfo.lChannel = channel; //预览通道号
  156. playInfo.dwStreamType = 0; //0-主码流,1-子码流,2-码流3,3-码流4,以此类推
  157. playInfo.dwLinkMode = 0; //0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
  158. playInfo.bBlocked = 1; //0- 非阻塞取流,1- 阻塞取流
  159. /* 设置回调函数 */
  160. realPlayHandle = NET_DVR_RealPlay_V40(m_loginID, &playInfo, realDataCallBack, nullptr);
  161. if (realPlayHandle < 0)
  162. {
  163. SPDLOG_ERROR("NET_DVR_RealPlay_V40()调用错误,错误代码:{}",NET_DVR_GetLastError());
  164. return;
  165. }
  166. /* 延时一定时间,这里延时也可以使用一个条件变量,在另一个线程控制通断 */
  167. std::this_thread::sleep_for(std::chrono::seconds(10));
  168. //关闭预览
  169. NET_DVR_StopRealPlay(realPlayHandle);
  170. SPDLOG_DEBUG("实时获取数据结束");
  171. }
  172. /* 智能检索 */
  173. bool HKCamera::smartSearch(int channel, const QDateTime& start, const QDateTime& end)
  174. {
  175. SPDLOG_LOGGER_INFO(m_logger,"智能检索,通道号:{},时间段:{} - {}",channel,start.toString("yyyy-MM-dd hh:mm:ss").toStdString(),end.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  176. LPNET_DVR_SMART_SEARCH_PARAM_V40 lpSmartSearchParam = new NET_DVR_SMART_SEARCH_PARAM_V40;
  177. NET_DVR_SmartSearch_V40(m_loginID, lpSmartSearchParam);
  178. return true;
  179. }
  180. /* 按照时间查找文件,主要是查找该时间段的文件是否存在 */
  181. bool HKCamera::findFileWithTime(int channel,const QDateTime& start,const QDateTime& end)
  182. {
  183. int findHandle = 0;
  184. /* 根据版本选择查询的API,这个版本是自己定的,不一定对 */
  185. if(m_sdkVersion == 5)
  186. {
  187. /* 设置查询条件 */
  188. NET_DVR_FILECOND_V50 findCond;
  189. findCond.dwFileType = 0xFF; /* 文件类型 */
  190. findCond.struStreamID.dwSize = sizeof(NET_DVR_STREAM_INFO);
  191. findCond.struStreamID.dwChannel = channel; /* 通道号 */
  192. findCond.byIsLocked = 0xff; /* 是否锁定文件 */
  193. findCond.byNeedCard = 0; /* 是否需要查询卡,0不需要 */
  194. /* 设置开始时间 */
  195. findCond.struStartTime.wYear = start.date().year();
  196. findCond.struStartTime.byMonth = start.date().month();
  197. findCond.struStartTime.byDay = start.date().day();
  198. findCond.struStartTime.byHour = start.time().hour();
  199. findCond.struStartTime.byMinute = start.time().minute();
  200. findCond.struStartTime.bySecond = start.time().second();
  201. /* 设置结束时间 */
  202. findCond.struStopTime.wYear = end.date().year();
  203. findCond.struStopTime.byMonth = end.date().month();
  204. findCond.struStopTime.byDay = end.date().day();
  205. findCond.struStopTime.byHour = end.time().hour();
  206. findCond.struStopTime.byMinute = end.time().minute();
  207. findCond.struStopTime.bySecond = end.time().second();
  208. /* 查找录像文件 */
  209. findHandle = NET_DVR_FindFile_V50(m_loginID, &findCond);
  210. }
  211. else if(m_sdkVersion == 3)
  212. {
  213. NET_DVR_FILECOND findCond;
  214. findCond.dwFileType = 0xff; /* 文件类型 */
  215. findCond.lChannel = channel; /* 通道号 */
  216. findCond.dwIsLocked = 0xff; /* 所有文件 */
  217. findCond.dwUseCardNo = 0; /* 不查询卡 */
  218. findCond.struStartTime.dwYear = start.date().year();
  219. findCond.struStartTime.dwMonth = start.date().month();
  220. findCond.struStartTime.dwDay = start.date().day();
  221. findCond.struStartTime.dwHour = start.time().hour();
  222. findCond.struStartTime.dwMinute = start.time().minute();
  223. findCond.struStartTime.dwSecond = start.time().second();
  224. findCond.struStopTime.dwYear = end.date().year();
  225. findCond.struStopTime.dwMonth = end.date().month();
  226. findCond.struStopTime.dwDay = end.date().day();
  227. findCond.struStopTime.dwHour = end.time().hour();
  228. findCond.struStopTime.dwMinute = end.time().minute();
  229. findCond.struStopTime.dwSecond = end.time().second();
  230. /* 查找录像文件 */
  231. findHandle = NET_DVR_FindFile_V30(m_loginID, &findCond);
  232. }
  233. if(findHandle < 0)
  234. {
  235. SPDLOG_LOGGER_ERROR(m_logger,"查找文件失败,错误代码:{}",NET_DVR_GetLastError());
  236. NET_DVR_FindClose_V30(findHandle);
  237. return false;
  238. }
  239. SPDLOG_LOGGER_DEBUG(m_logger,"查找文件成功! findHandle:{}",findHandle);
  240. /* 逐个获取查询结果 */
  241. NET_DVR_FINDDATA_V50 fileData;
  242. // char fileName[100] = { 0 }; //需要下载的文件
  243. QString fileName;
  244. int fileNum = 0;
  245. bool isFind = false;
  246. while (true)
  247. {
  248. int result = NET_DVR_FindNextFile_V50(findHandle, &fileData);
  249. /* 正在查找中 */
  250. if (result == NET_DVR_ISFINDING)
  251. {
  252. SPDLOG_LOGGER_DEBUG(m_logger,"正在查找中...");
  253. continue;
  254. }
  255. /* 查找到文件 */
  256. else if (result == NET_DVR_FILE_SUCCESS)
  257. {
  258. fileNum++;
  259. // printf("find file no: %d, file name:%s\n", fileNum, fileData.sFileName);
  260. if (fileNum == 1)
  261. {
  262. // strcpy(fileName, fileData.sFileName);
  263. fileName.clear();
  264. fileName = QString::asprintf("%s", fileData.sFileName);
  265. SPDLOG_LOGGER_INFO(m_logger,"查找到了文件名:{}", fileName.toStdString());
  266. }
  267. isFind = true;
  268. continue;
  269. }
  270. /* 没有文件,没有更多的文件 */
  271. else if (result == NET_DVR_FILE_NOFIND || result == NET_DVR_NOMOREFILE)
  272. {
  273. SPDLOG_LOGGER_INFO(m_logger,"没有其他文件,退出");
  274. break;
  275. }
  276. else
  277. {
  278. SPDLOG_LOGGER_WARN(m_logger,"查找失败,退出");
  279. // printf("find file fail for illegal get file state");
  280. break;
  281. }
  282. }
  283. //停止查找,释放资源
  284. if (findHandle >= 0)
  285. {
  286. SPDLOG_LOGGER_DEBUG(m_logger,"停止查找,释放资源...");
  287. NET_DVR_FindClose_V30(findHandle);
  288. }
  289. SPDLOG_LOGGER_INFO(m_logger, "查找文件结束");
  290. return isFind;
  291. }
  292. /* 查找一段时间的视频是否完整 */
  293. bool HKCamera::findFileIsComplete(int channel,const QDateTime& start,const QDateTime& end)
  294. {
  295. /* 刷新摄像机索引 */
  296. if(!NET_DVR_UpdateRecordIndex(m_loginID, channel))
  297. {
  298. auto err = NET_DVR_GetLastError();
  299. if(23 == err)
  300. {
  301. SPDLOG_LOGGER_DEBUG(m_logger,"刷新摄像机索引失败,设备不支持");
  302. }else {
  303. SPDLOG_LOGGER_DEBUG(m_logger,"刷新摄像机索引失败,错误代码:{}",err);
  304. }
  305. }
  306. int findHandle = 0;
  307. /* 根据版本选择查询的API,这个版本是自己定的,不一定对 */
  308. if(m_sdkVersion == 5)
  309. {
  310. /* 设置查询条件 */
  311. NET_DVR_FILECOND_V50 findCond;
  312. findCond.dwFileType = 0xFF; /* 文件类型 */
  313. findCond.struStreamID.dwSize = sizeof(NET_DVR_STREAM_INFO);
  314. findCond.struStreamID.dwChannel = channel; /* 通道号 */
  315. findCond.byIsLocked = 0xff; /* 是否锁定文件 */
  316. findCond.byNeedCard = 0; /* 是否需要查询卡,0不需要 */
  317. /* 设置开始时间 */
  318. findCond.struStartTime.wYear = start.date().year();
  319. findCond.struStartTime.byMonth = start.date().month();
  320. findCond.struStartTime.byDay = start.date().day();
  321. findCond.struStartTime.byHour = start.time().hour();
  322. findCond.struStartTime.byMinute = start.time().minute();
  323. findCond.struStartTime.bySecond = start.time().second();
  324. /* 设置结束时间 */
  325. findCond.struStopTime.wYear = end.date().year();
  326. findCond.struStopTime.byMonth = end.date().month();
  327. findCond.struStopTime.byDay = end.date().day();
  328. findCond.struStopTime.byHour = end.time().hour();
  329. findCond.struStopTime.byMinute = end.time().minute();
  330. findCond.struStopTime.bySecond = end.time().second();
  331. /* 查找录像文件 */
  332. findHandle = NET_DVR_FindFile_V50(m_loginID, &findCond);
  333. }
  334. else if(m_sdkVersion == 3)
  335. {
  336. NET_DVR_FILECOND findCond;
  337. findCond.dwFileType = 0xff; /* 文件类型 */
  338. findCond.lChannel = channel; /* 通道号 */
  339. findCond.dwIsLocked = 0xff; /* 所有文件 */
  340. findCond.dwUseCardNo = 0; /* 不查询卡 */
  341. findCond.struStartTime.dwYear = start.date().year();
  342. findCond.struStartTime.dwMonth = start.date().month();
  343. findCond.struStartTime.dwDay = start.date().day();
  344. findCond.struStartTime.dwHour = start.time().hour();
  345. findCond.struStartTime.dwMinute = start.time().minute();
  346. findCond.struStartTime.dwSecond = start.time().second();
  347. findCond.struStopTime.dwYear = end.date().year();
  348. findCond.struStopTime.dwMonth = end.date().month();
  349. findCond.struStopTime.dwDay = end.date().day();
  350. findCond.struStopTime.dwHour = end.time().hour();
  351. findCond.struStopTime.dwMinute = end.time().minute();
  352. findCond.struStopTime.dwSecond = end.time().second();
  353. /* 查找录像文件 */
  354. findHandle = NET_DVR_FindFile_V30(m_loginID, &findCond);
  355. }
  356. if(findHandle < 0)
  357. {
  358. SPDLOG_LOGGER_ERROR(m_logger,"查找文件失败,错误代码:{}",NET_DVR_GetLastError());
  359. NET_DVR_FindClose_V30(findHandle);
  360. return false;
  361. }
  362. SPDLOG_LOGGER_DEBUG(m_logger,"查找文件成功! findHandle:{}",findHandle);
  363. /* 逐个获取查询结果 */
  364. NET_DVR_FINDDATA_V50 fileData;
  365. RetFileInfo fileInfo;
  366. // char fileName[100] = { 0 }; //需要下载的文件
  367. QString fileName;
  368. int fileNum = 0;
  369. bool isComplete = false;
  370. while (true)
  371. {
  372. int result = NET_DVR_FindNextFile_V50(findHandle, &fileData);
  373. /* 正在查找中 */
  374. if (result == NET_DVR_ISFINDING)
  375. {
  376. SPDLOG_LOGGER_DEBUG(m_logger,"正在查找中...");
  377. continue;
  378. }
  379. /* 查找到文件 */
  380. else if (result == NET_DVR_FILE_SUCCESS)
  381. {
  382. fileNum++;
  383. // printf("find file no: %d, file name:%s\n", fileNum, fileData.sFileName);
  384. // if (fileNum == 1)
  385. // {
  386. // strcpy(fileName, fileData.sFileName);
  387. fileName.clear();
  388. fileName = QString::asprintf("%s", fileData.sFileName);
  389. /* 将数据转换成QDateTime */
  390. fileInfo.fileName = fileName;
  391. fileInfo.setStartTime(fileData.struStartTime);
  392. fileInfo.setEndTime(fileData.struStopTime);
  393. fileInfo.fileSize = fileData.dwFileSize;
  394. // SPDLOG_LOGGER_INFO(m_logger,"查找到了文件名:{}", fileName.toStdString());
  395. // SPDLOG_LOGGER_INFO(m_logger,"开始时间:{}",fileInfo.startTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  396. // SPDLOG_LOGGER_INFO(m_logger,"结束时间:{}",fileInfo.endTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  397. // SPDLOG_LOGGER_INFO(m_logger,"文件大小:{}",fileInfo.fileSize);
  398. SPDLOG_LOGGER_INFO(m_logger, "--------------------------------------------------------------");
  399. /* 判断时间是否覆盖了传入的时间 */
  400. if(fileInfo.endTime >= end)
  401. {
  402. isComplete = true;
  403. SPDLOG_LOGGER_INFO(m_logger,"摄像机视频已达到结束时间,开始时间:{},结束时间:{}",
  404. fileInfo.startTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
  405. fileInfo.endTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  406. } else
  407. {
  408. SPDLOG_LOGGER_INFO(m_logger,"视频文件未覆盖结束时间,摄像机已存储的视频最新时间: {}", fileInfo.endTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  409. SPDLOG_LOGGER_INFO(m_logger,"需要时间段:{} - {}",start.toString("yyyy-MM-dd hh:mm:ss").toStdString(),end.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  410. }
  411. // }
  412. continue;
  413. }
  414. /* 没有文件,没有更多的文件 */
  415. else if (result == NET_DVR_FILE_NOFIND || result == NET_DVR_NOMOREFILE)
  416. {
  417. SPDLOG_LOGGER_INFO(m_logger,"没有其他文件,退出查找");
  418. break;
  419. }
  420. else
  421. {
  422. SPDLOG_LOGGER_WARN(m_logger,"视频文件查找失败,退出");
  423. // printf("find file fail for illegal get file state");
  424. break;
  425. }
  426. }
  427. //停止查找,释放资源
  428. if (findHandle >= 0)
  429. {
  430. SPDLOG_LOGGER_DEBUG(m_logger,"停止查找视频,释放资源...");
  431. NET_DVR_FindClose_V30(findHandle);
  432. }
  433. SPDLOG_LOGGER_INFO(m_logger, "查找视频文件结束");
  434. return isComplete;
  435. }
  436. /* 按照时间段下载记录的文件 */
  437. bool HKCamera::downloadRecordFile(int channel,const QString& savePath,const QDateTime& start,const QDateTime& end)
  438. {
  439. SPDLOG_LOGGER_INFO(m_logger,"下载文件,保存路径:{}",savePath.toStdString());
  440. SPDLOG_LOGGER_INFO(m_logger,"下载时间段:{} - {}",start.toString("yyyy-MM-dd hh:mm:ss").toStdString(),end.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  441. SPDLOG_LOGGER_INFO(m_logger,"下载通道号:{}",channel);
  442. NET_DVR_PLAYCOND downloadCond = {0};
  443. /* 这里好像也没有区分模拟通道和数字通道 */
  444. downloadCond.dwChannel = channel;
  445. /* 设置开始时间和结束时间 */
  446. downloadCond.struStartTime.dwYear = start.date().year();
  447. downloadCond.struStartTime.dwMonth = start.date().month();
  448. downloadCond.struStartTime.dwDay = start.date().day();
  449. downloadCond.struStartTime.dwHour = start.time().hour();
  450. downloadCond.struStartTime.dwMinute = start.time().minute();
  451. downloadCond.struStartTime.dwSecond = start.time().second();
  452. downloadCond.struStopTime.dwYear = end.date().year();
  453. downloadCond.struStopTime.dwMonth = end.date().month();
  454. downloadCond.struStopTime.dwDay = end.date().day();
  455. downloadCond.struStopTime.dwHour = end.time().hour();
  456. downloadCond.struStopTime.dwMinute = end.time().minute();
  457. downloadCond.struStopTime.dwSecond = end.time().second();
  458. /* 按时间下载 */
  459. int playBack;
  460. /* 第二个参数是保存的文件名称 */
  461. std::string tmpStr = savePath.toStdString();
  462. playBack = NET_DVR_GetFileByTime_V40(m_loginID, &tmpStr[0], &downloadCond);
  463. // playBack = NET_DVR_GetFileByTime_V40(m_loginID, savePath.toStdString().data(), &downloadCond);
  464. if(playBack < 0)
  465. {
  466. SPDLOG_LOGGER_ERROR(m_logger,"NET_DVR_GetFileByTime_V40 错误,错误代码:{}", NET_DVR_GetLastError());
  467. return false;
  468. }
  469. /* 开始下载 */
  470. if(!NET_DVR_PlayBackControl_V40(playBack, NET_DVR_PLAYSTART, NULL, 0, NULL,NULL))
  471. {
  472. SPDLOG_LOGGER_ERROR(m_logger,"NET_DVR_PlayBackControl_V40 错误,错误代码:{}",NET_DVR_GetLastError());
  473. return false;
  474. }
  475. int nPos = 0;
  476. /* 等待下载完成的过程,1秒刷新一次,按照时间下载不支持进度,返回的都是0 */
  477. for(nPos = 0; nPos < 100 && nPos>=0; nPos = NET_DVR_GetDownloadPos(playBack))
  478. {
  479. SPDLOG_LOGGER_INFO(m_logger,"下载中... {}",nPos);
  480. std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  481. }
  482. if(!NET_DVR_StopGetFile(playBack))
  483. {
  484. SPDLOG_LOGGER_DEBUG(m_logger,"停止下载文件失败,错误代码 {}",NET_DVR_GetLastError());
  485. return false;
  486. }
  487. if(nPos<0||nPos>100)
  488. {
  489. SPDLOG_LOGGER_ERROR(m_logger,"下载错误,错误代码 {}", NET_DVR_GetLastError());
  490. /* 判断文件大小,等于0,则删除 */
  491. QFile file(savePath);
  492. if(file.exists() && file.size() == 0)
  493. {
  494. file.remove();
  495. }
  496. return false;
  497. }
  498. SPDLOG_LOGGER_INFO(m_logger,"下载成功!");
  499. return true;
  500. }
  501. /* 打开视频文件,顺便初始化播放类 */
  502. CVideoPlayer* HKCamera::openVideoFile(const QString& fileName)
  503. {
  504. /* 初始化播放实例 */
  505. SPDLOG_DEBUG("...新建一个播放窗口...");
  506. auto videoPlayer = new CVideoPlayer;
  507. // videoPlayer->setPlayVedio(fileName);
  508. videoPlayer->openPlayVedio(fileName);
  509. m_listPlayer.append(videoPlayer);
  510. return videoPlayer;
  511. }
  512. /* 播放视频 */
  513. void HKCamera::playVideo(CVideoPlayer* videoPlayer)
  514. {
  515. if(!m_listPlayer.contains(videoPlayer))
  516. {
  517. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  518. return;
  519. }
  520. videoPlayer->play();
  521. }
  522. /* 关闭播放,清空播放类 */
  523. void HKCamera::closePlay(CVideoPlayer* videoPlayer)
  524. {
  525. if(!m_listPlayer.contains(videoPlayer))
  526. {
  527. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  528. return;
  529. }
  530. SPDLOG_DEBUG("...关闭播放...");
  531. if(videoPlayer != nullptr)
  532. {
  533. /* 获取视频文件名称路径 */
  534. QString fileName = videoPlayer->getFileName();
  535. stop(videoPlayer);
  536. SPDLOG_DEBUG("...删除播放类...");
  537. SPDLOG_INFO("删除本地视频: {}", fileName.toStdString());
  538. QFile file(fileName);
  539. if(file.exists())
  540. {
  541. file.remove();
  542. }
  543. m_listPlayer.removeOne(videoPlayer);
  544. delete videoPlayer;
  545. videoPlayer = nullptr;
  546. }
  547. }
  548. /* 暂停播放 */
  549. void HKCamera::pause(CVideoPlayer* videoPlayer)
  550. {
  551. if(!m_listPlayer.contains(videoPlayer))
  552. {
  553. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  554. return;
  555. }
  556. videoPlayer->pause();
  557. }
  558. /* 停止播放 */
  559. void HKCamera::stop(CVideoPlayer* videoPlayer)
  560. {
  561. if(!m_listPlayer.contains(videoPlayer))
  562. {
  563. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  564. return;
  565. }
  566. videoPlayer->stop();
  567. }
  568. /* 继续播放 */
  569. void HKCamera::continuePlay(CVideoPlayer* videoPlayer)
  570. {
  571. if(!m_listPlayer.contains(videoPlayer))
  572. {
  573. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  574. return;
  575. }
  576. videoPlayer->play();
  577. }
  578. /* 获取播放时长 */
  579. unsigned long long HKCamera::getPlayDuration(CVideoPlayer* videoPlayer)
  580. {
  581. if(!m_listPlayer.contains(videoPlayer))
  582. {
  583. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  584. return -1;
  585. }
  586. SPDLOG_TRACE("获取播放时长:{}",videoPlayer->getDuration());
  587. return videoPlayer->getDuration();
  588. }
  589. /* 设置当前播放位置 */
  590. void HKCamera::setCurrentPlayPos(CVideoPlayer* videoPlayer, unsigned long long pos)
  591. {
  592. if(!m_listPlayer.contains(videoPlayer))
  593. {
  594. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  595. return;
  596. }
  597. videoPlayer->setCurrentPos(pos);
  598. }
  599. /* 获取当前播放位置 */
  600. unsigned long long HKCamera::getCurrentPlayPos(CVideoPlayer* videoPlayer)
  601. {
  602. if(!m_listPlayer.contains(videoPlayer))
  603. {
  604. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  605. return -1;
  606. }
  607. SPDLOG_TRACE("获取当前播放位置:{}",videoPlayer->getCurrentPos());
  608. return videoPlayer->getCurrentPos();
  609. }
  610. /* 获取播放状态 */
  611. bool HKCamera::getPlayState(CVideoPlayer* videoPlayer)
  612. {
  613. if(!m_listPlayer.contains(videoPlayer))
  614. {
  615. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  616. return false;
  617. }
  618. return videoPlayer->getPlayStatus();
  619. }
  620. /* 设置播放窗口的父窗口 */
  621. void HKCamera::setVideoParent(CVideoPlayer* videoPlayer, QWidget* parent)
  622. {
  623. if(!m_listPlayer.contains(videoPlayer))
  624. {
  625. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  626. return;
  627. }
  628. videoPlayer->setParent(parent);
  629. SPDLOG_LOGGER_TRACE(m_logger,"设置播放窗口的父窗口");
  630. }
  631. /* 设置音量 */
  632. void HKCamera::setVolume(CVideoPlayer* videoPlayer, int volume)
  633. {
  634. if(volume <0 || volume > 100)
  635. {
  636. SPDLOG_LOGGER_WARN(m_logger,"音量设置错误,范围是0-100");
  637. return;
  638. }
  639. }
  640. /* 获取音量 */
  641. int HKCamera::getVolume(CVideoPlayer* videoPlayer)
  642. {
  643. return 0;
  644. }
  645. /* 检查指针是否在列表容器中 */
  646. bool HKCamera::checkVideoPlayerInList(CVideoPlayer* videoPlayer)
  647. {
  648. if(!m_listPlayer.contains(videoPlayer))
  649. {
  650. SPDLOG_LOGGER_WARN(m_logger, "窗口 {} 不在列表中",(void *)videoPlayer);
  651. return false;
  652. }
  653. return true;
  654. }
  655. /* 设置回调函数 */
  656. void HKCamera::setCallBack(CallBackType type, std::function<Play_CallBack> playCallback,void* pContext)
  657. {
  658. for(auto& it : m_listPlayer)
  659. {
  660. if(type == CallBackType::PlayCallBack)
  661. {
  662. it->setPlayCallBack(playCallback, pContext);
  663. }
  664. else if(type == CallBackType::DownloadCallBack)
  665. {
  666. }
  667. }
  668. }
  669. /**
  670. * @brief 异常回调函数
  671. *
  672. * @param type 异常类型,目前就知道以下几个
  673. * @param userID
  674. * @param handle
  675. * @param user
  676. */
  677. void HKCamera::exceptionCallBack(unsigned int type, int userID,int handle,void* user)
  678. {
  679. /* 异常代码是16进制的 */
  680. SPDLOG_WARN("调用了异常回调函数,异常代码:{:#X}",type);
  681. switch(type)
  682. {
  683. /* 报警上传时网络异常 */
  684. case EXCEPTION_ALARM:
  685. SPDLOG_WARN("报警上传时网络异常!!!");
  686. //TODO: 关闭报警上传
  687. break;
  688. /* 网络预览时异常 */
  689. case EXCEPTION_PREVIEW:
  690. SPDLOG_WARN("网络预览时网络异常!!!");
  691. //TODO: 关闭网络预览
  692. break;
  693. /* 预览时重连 */
  694. case EXCEPTION_RECONNECT:
  695. break;
  696. case EXCEPTION_PLAYBACK:
  697. SPDLOG_WARN("回放异常!");
  698. break;
  699. default:
  700. break;
  701. }
  702. }
  703. /**
  704. * @brief 实时预览回调函数,没有解码的数据流
  705. *
  706. * @param realHandle 操作句柄
  707. * @param dataType 数据类型
  708. * @param pBuffer 数据指针
  709. * @param bufSize 数据大小
  710. * @param user
  711. */
  712. void HKCamera::realDataCallBack(LONG realHandle, DWORD dataType, BYTE *pBuffer,DWORD bufSize,void* user)
  713. {
  714. // SPDLOG_DEBUG("realDataCallBack接收到了数据,数据大小为:{}",bufSize);
  715. /* 获取播放的窗口指针 */
  716. unsigned int hWnd = 0;
  717. switch (dataType)
  718. {
  719. /* 系统头数据 */
  720. case NET_DVR_SYSHEAD:
  721. if (m_playPort >= 0)
  722. {
  723. break; //该通道取流之前已经获取到句柄,后续接口不需要再调用
  724. }
  725. SPDLOG_DEBUG("系统头数据");
  726. // if (!PlayM4_GetPort(&m_playPort)) //获取播放库未使用的通道号
  727. // {
  728. // break;
  729. // }
  730. //m_iPort = lPort; //第一次回调的是系统头,将获取的播放库port号赋值给全局port,下次回调数据时即使用此port号播放
  731. if (bufSize > 0)
  732. {
  733. // if (!PlayM4_SetStreamOpenMode(m_playPort, STREAME_REALTIME)) //设置实时流播放模式
  734. // {
  735. // break;
  736. // }
  737. // if (!PlayM4_OpenStream(m_playPort, pBuffer, bufSize, 1024*1024)) //打开流接口
  738. // {
  739. // break;
  740. // }
  741. // if (!PlayM4_Play(m_playPort, hWnd)) //播放开始
  742. // {
  743. // break;
  744. // }
  745. }
  746. break;
  747. /* 视频流数据(包括复合流和音视频分开的视频流数据) */
  748. case NET_DVR_STREAMDATA:
  749. if (bufSize > 0 && m_playPort != -1)
  750. {
  751. // if (!PlayM4_InputData(m_playPort, pBuffer, bufSize))
  752. // {
  753. // break;
  754. // }
  755. }
  756. SPDLOG_DEBUG("视频流数据,bufSize = {}",bufSize);
  757. break;
  758. /* 其他数据 */
  759. default:
  760. if (bufSize > 0 && m_playPort != -1)
  761. {
  762. // if (!PlayM4_InputData(m_playPort, pBuffer, bufSize))
  763. // {
  764. // break;
  765. // }
  766. }
  767. SPDLOG_DEBUG("其他数据");
  768. break;
  769. }
  770. }