Video convergence protocol security monitoring system EasyCVR development support Dahua SDK access equipment video playback process description

Many consultants or old customers know that the EasyCVR platform developed by Tsingsee Green Rhinoceros Video supports private protocols. It initially supported HIKSDK, and then developed Ehome protocol access. Up to now, we have completed Dahua SDK access. stand by. This article talks about the process of EasyCVR platform access to Dahua SDK equipment for video playback.

42.png

Video playback means that the client remotely plays the video files in the specified time period in the device to find the required video information. The playback function supports multiple playback operations, such as normal playback, pause, fast playback, slow playback, drag playback, etc.

Video review.png

  1. Complete the SDK initialization process.
  2. After the initialization is successful, call CLIENT_LoginEx2 to log in to the device.
  3. After successful login, call CLIENT_SetDeviceMode twice to set the stream type during playback and the type of video file during playback.
  4. After successful login, call CLIENT_PlayBackByTimeEx to start playback, the hWnd parameter is NULL, and the fDownLoadDataCallBack parameter is a valid callback function pointer.
  5. After the SDK receives the playback data, it calls back the playback data to the user through the set fDownLoadDataCallBack callback function. The user saves the playback data in the callback function. After leaving the callback function, the playback data is decoded and played back through the third-party library.
  6. During playback, call CLIENT_SlowPlayBack to realize slow playback, CLIENT_FasePlayBack to realize fast playback, CLIENT_NormalPlayBack to realize normal playback speed
    , CLIENT_PausePlayBack to realize pause/resume, CLIENT_SeekPlayBack to realize drag
    playback, and the corresponding interface of the third-party library must be called.
  7. After the playback is used, call CLIENT_StopPlayBack to stop playback.
  8. After the service is used, CLIENT_Logout is called to log out the user.
  9. After using the SDK function, call CLIENT_Cleanup to release SDK resources.

The Dahua SDK decoding and playback process is shown in the following figure:

43.png

#include <stdio.h> 
#include "dhnetsdk.h" 
#pragma comment(lib , "dhnetsdk.lib") 
static BOOL g_bNetSDKInitFlag = FALSE; 
static LLONG g_lLoginHandle = 0L; 
static LLONG g_lPlayHandle = 0L; 
static char g_szDevIp[32] = "172.11.1.6"; 
static WORD g_nPort = 37777; // tcp 连接端口,需与期望登录设备页面 tcp 端口配置一 
static char g_szUserName[64] = "admin"; 
static char g_szPasswd[64] = "admin"; 
//************************************************************************* 
******** 
// 常用回调集合声明 
// 设备断线回调函数 
// 不建议在该回调函数中调用SDK接口 
// 通过 CLIENT_Init 设置该回调函数,当设备出现断线时,SDK 会调用该函数。 
void CALLBACK DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, 
DWORD dwUser); 
// 断线重连成功回调函数 
// 不建议在该回调函数中调用 SDK 接口 
// 通过 CLIENT_SetAutoReconnect 设置该回调函数,当已断线的设备重连成功时,SDK 会 
调用该函数。 
void CALLBACK HaveReConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, 
LDWORD dwUser); 
// 回放进度回调函数 
// 不建议在该回调函数中调用SDK接口 
// 通过 CLIENT_PlayBackByTimeEx 设置该回调函数,当接收到设备端的回放数据时,SDK会调用该函数 
void CALLBACK DownLoadPosCallBack(LLONG lPlayHandle, DWORD dwTotalSize, DWORD 
dwDownLoadSize, LDWORD dwUser); 
// 回放数据回调函数 
// 不建议在该回调函数中调用SDK接口 
// 当设置该回调函数时,若对应的hWnd参数为 NULL,参数返回,0:表示本次回调失败,下次回调会返回相同的数据,1:表示本次回调成功,下次回调会返回后续的数据 
// 当设置该回调函数时,若对应的 hWnd 参数不为 NULL,则不管回调函数返回值为多少都认为 
回调成功,下次回调会返回后续的数据 
// 通过CLIENT_PlayBackByTimeEx设置该回调函数,当接收到设备端的回放数据时,SDK 
40 41 
会调用该函数。 
int CALLBACK DataCallBack(LLONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, 
DWORD dwBufSize, LDWORD dwUser); 
//************************************************************** *********** 
************ 
void InitTest() 
{ 
// 初始化 SDK 
g_bNetSDKInitFlag = CLIENT_Init(DisConnectFunc, 0); 
if (FALSE == g_bNetSDKInitFlag) 
{ 
printf("Initialize client SDK fail; \n"); 
return; 
} 
else 
{ 
printf("Initialize client SDK done; \n"); 
} 
// 获取 SDK 版本信息 
// 此操作为可选操作 
DWORD dwNetSdkVersion = CLIENT_GetSDKVersion(); 
printf("NetSDK version is [%d]\n", dwNetSdkVersion); 
// 设置断线重连回调接口,设置过断线重连成功回调函数后,当设备出现断线情况,SDK内部会自动进行重连操作
// 此操作为可选操作,但建议用户进行设置 
CLIENT_SetAutoReconnect(&HaveReConnect, 0); 
// 设置登录超时时间和尝试次数 
// 此操作为可选操作 
int nWaitTime = 5000; // 登录请求响应超时时间设置为5s 
int nTryTimes = 3; // 登录时尝试建立链接3次 
CLIENT_SetConnectTime(nWaitTime, nTryTimes); 
// 设置更多网络参数,NET_PARAM 的 nWaittime,nConnectTryNum 成员与 
CLIENT_SetConnectTime 接口设置的登录设备超时时间和尝试次数意义相同 
// 此操作为可选操作 
NET_PARAM stuNetParm = {0}; 42 
stuNetParm.nConnectTime = 3000; // 登录时尝试建立链接的超时时间 
CLIENT_SetNetworkParam(&stuNetParm); 
NET_DEVICEINFO_Ex stDevInfoEx = {0}; 
int nError = 0; 
while(0 == g_lLoginHandle) 
{ 
// 登录设备 
g_lLoginHandle = CLIENT_LoginEx2(g_szDevIp, g_nPort, g_szUserName, 
g_szPasswd, EM_LOGIN_SPEC_CAP_TCP, NULL, &stDevInfoEx, &nError); 
if(0 == g_lLoginHandle) 
{ 
// 根据错误码,可以在 dhnetsdk.h 中找到相应的解释,此处打印的是 16 进制,头文件中是十进制,其中的转换需注意 
// 例如: 
// #define NET_NOT_SUPPORTED_EC(23) // 当前 SDK 未支持该功能,对应的错误码为 0x80000017, 23 对应的 16 进制为 0x17 
printf("CLIENT_LoginEx2 %s[%d]Failed!Last Error[%x]\n" , g_szDevIp , 
g_nPort , CLIENT_GetLastError()); 
} 
else 
{ 
printf("CLIENT_LoginEx2 %s[%d] Success\n" , g_szDevIp , g_nPort); 
} 
// 用户初次登录设备,可能要初始化一些数据才能正常实现业务功能,所以建议登录后等待一小段时间,具体等待时间因设备而异 
Sleep(1000); 
printf("\n"); 
} 
} 
void RunTest() 
{ 
if (FALSE == g_bNetSDKInitFlag) 
{ 
return; 
} 
if (0 == g_lLoginHandle) 
{ 
return; 
} 43 
// 录像回放功能 
// 设置回放时的码流类型 
int nStreamType = 0; // 0-主辅码流,1-主码流,2-辅码流 
CLIENT_SetDeviceMode(g_lLoginHandle, DH_RECORD_STREAM_TYPE, 
&nStreamType); 
// 设置回放时的录像文件类型 
NET_RECORD_TYPE emFileType = NET_RECORD_TYPE_ALL; // 所有录像 
CLIENT_SetDeviceMode(g_lLoginHandle, DH_RECORD_TYPE, &emFileType); 
//开启录像回放 
int nChannelID = 0; // 通道号 
NET_TIME stuStartTime = {0}; 
stuStartTime.dwYear = 2015; 
stuStartTime.dwMonth = 11; 
stuStartTime.dwDay = 20; 
NET_TIME stuStopTime = {0}; 
stuStopTime.dwYear = 2015; 
stuStopTime.dwMonth = 11; 
stuStopTime.dwDay = 21; 
// 函数形参 hWnd 需为 NULL 
// 函数形参 fDownLoadDataCallBack 需为 有效回调函数指针 
g_lPlayHandle = CLIENT_PlayBackByTimeEx(g_lLoginHandle, nChannelID, 
&stuStartTime, &stuStopTime, NULL, &DownLoadPosCallBack, NULL, &DataCallBack, 
NULL); 
if (g_lPlayHandle == 0) 
{ 
printf("CLIENT_PlayBackByTimeEx: failed! Error code: %x.\n", 
CLIENT_GetLastError()); 
} 
// 用户可根据需求实现回放控制 
// 由于是第三方库解码,用户在调用 SDK 的回放控制接口的同时,还需要调用第三方库相应的控制接口 
// 由于这个是控制台 demo,无法将录像回放和回放控制同时展现给用户,这里提供示例 
代码用于参考 
// CLIENT_SlowPlayBack 实现慢放 
/* 示例代码 
if (FALSE == CLIENT_SlowPlayBack (g_lPlayHandle)) 
{ 44 
printf("CLIENT_SlowPlayBack Failed, g_lPlayHandle[%x]!Last 
Error[%x]\n" , g_lPlayHandle, CLIENT_GetLastError()); 
} 
// 第三方库相应接口调用 
*/ 
// CLIENT_FastPlayBack 实现快放 
/* 示例代码 
if (FALSE == CLIENT_FastPlayBack (g_lPlayHandle)) 
{ 
printf("CLIENT_FastPlayBack Failed, g_lPlayHandle[%x]!Last 
Error[%x]\n" , g_lPlayHandle, CLIENT_GetLastError()); 
} 
// 第三方库相应接口调用 
*/ 
// CLIENT_NormalPlayBack 实现正常播放速度 
/* 示例代码 
if (FALSE == CLIENT_NormalPlayBack (g_lPlayHandle)) 
{ 
printf("CLIENT_NormalPlayBack Failed, g_lPlayHandle[%x]!Last 
Error[%x]\n" , g_lPlayHandle, CLIENT_GetLastError()); 
} 
// 第三方库相应接口调用 
*/ 
// CLIENT_PausePlayBack 实现暂停/恢复 
/* 示例代码 
if (FALSE == CLIENT_PausePlayBack (g_lPlayHandle, TRUE)) 
{ 
printf("CLIENT_PausePlayBack Failed, g_lPlayHandle[%x]!Last 
Error[%x]\n" , g_lPlayHandle, CLIENT_GetLastError()); 
} 
// 第三方库相应接口调用 
*/ 
// CLIENT_SeekPlayBack 实现拖动播放 
/* 示例代码 
int nOffsetSeconds = 2 * 60 * 60; // 拖动至 stuStartTime 后 2*60*60 秒的位 
置开始回放 if (FALSE == CLIENT_SeekPlayBack (g_lPlayHandle, nOffsetSeconds, 0)) 
{ 
printf("CLIENT_SeekPlayBack Failed, g_lPlayHandle[%x]!Last 
Error[%x]\n" , g_lPlayHandle, CLIENT_GetLastError()); 
} 
// 第三方库相应接口调用 
*/ 
} 
void EndTest() 
{ 
printf("input any key to quit!\n"); 
getchar(); 
// 关闭回放 
if (0 != g_lPlayHandle) 
{ 
if (FALSE == CLIENT_StopPlayBack(g_lPlayHandle)) 
{ 
printf("CLIENT_StopPlayBack Failed, g_lRealHandle[%x]!Last 
Error[%x]\n" , g_lPlayHandle, CLIENT_GetLastError()); 
} 
else 
{ 
g_lPlayHandle = 0; 
} 
} 
// 退出设备 
if (0 != g_lLoginHandle) 
{ 
if(FALSE == CLIENT_Logout(g_lLoginHandle)) 
{ 
printf("CLIENT_Logout Failed!Last Error[%x]\n", 
CLIENT_GetLastError()); 
} 
else 
{ 
g_lLoginHandle = 0; 
} 
} 
// 清理初始化资源 
if (TRUE == g_bNetSDKInitFlag) 
{ 
CLIENT_Cleanup(); 
45 46 
g_bNetSDKInitFlag = FALSE; 
} 
return; 
} 
int main() 
{ 
InitTest(); 
RunTest(); 
EndTest(); 
return 0; 
} 
//************************************************************************* 
******** 
// 常用回调集合定义 
void CALLBACK DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, 
DWORD dwUser) 
{ 
printf("Call DisConnectFunc\n"); 
printf("lLoginID[0x%x]", lLoginID); 
if (NULL != pchDVRIP) 
{ 
printf("pchDVRIP[%s]\n", pchDVRIP); 
} 
printf("nDVRPort[%d]\n", nDVRPort); 
printf("dwUser[%p]\n", dwUser); 
printf("\n"); 
} 
void CALLBACK HaveReConnect(LLONG lLoginID, char *pchDVRIP, LONG nD VRPort, 
LDWORD dwUser) 
{ 
printf("Call HaveReConnect\n"); 
printf("lLoginID[0x%x]", lLoginID); 
if (NULL != pchDVRIP) 
{ 
printf("pchDVRIP[%s]\n", pchDVRIP); 
} 
printf("nDVRPort[%d]\n", nDVRPort); 47 
printf("dwUser[%p]\n", dwUser); 
printf("\n"); 
} 
void CALLBACK DownLoadPosCallBack(LLONG lPlayHandle, DWORD dwTotalSize, DWORD 
dwDownLoadSize, LDWORD dwUser) 
{ 
// 若多个回放/下载使用相同的进度回调函数,则用户可通过 lPlayHandle 进行一一对应 
if (lPlayHandle == g_lPlayHandle) 
{ 
printf("lPlayHandle[%p]\n", lPlayHandle); 
printf("dwTotalSize[%d]\n", dwTotalSize); 
printf("dwDownLoadSize[%d]\n", dwDownLoadSize); 
printf("dwUser[%p]\n", dwUser); 
printf("\n"); 
} 
} 
int CALLBACK DataCallBack(LLONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, 
DWORD dwBufSize, LDWORD dwUser) 
{ 
int nRet = 0; 
printf("call DataCallBack\n"); 
// 若多个回放/下载使用相同的数据回调函数,则用户可通过 lRealHandle 进行一一对应 
if(lRealHandle == g_lPlayHandle) 
{ 
BOOL bSuccess = TRUE; 
// 以下打印在回放/下载时会造成刷屏现象,请注意 
printf("lPlayHandle[%p]\n", lRealHandle); 
printf("dwDataType[%d]\n", dwDataType); 
printf("pBuffer[%p]\n", pBuffer); 
printf("dwBufSize[%d]\n", dwBufSize); 
printf("dwUser[%p]\n", dwUser); 
printf("\n"); 
switch(dwDataType) 
{ 
case 0: 
//Original data 
// 用户在此处保存码流数据,离开回调函数后再进行解码或转发等一系列处理 
nRet = 1;// 
break; 48 
case 1: 
//Standard video data 
break; 
case 2: 
//yuv data 
break; 
case 3: 
//pcm audio data 
break; 
case 4: 
//Original audio data 
break; 
default: 
break; 
} 
} 
return nRet; 
}

Guess you like

Origin blog.csdn.net/EasyNVS/article/details/112986601