About the secondary development of Hikvision network cameras

In the past week, I have been studying the secondary development of Hikvision's network cameras, and have been struggling for a long time. I finally got through a part today, and I wrote it down in the hope that it can help more people. Now it is tested with VS2013 + opencv.

First of all, I recommend two blog posts that helped me a lot:

               http://blog.csdn.net/wanghuiqi2008/article/details/31410509

               This article explains the framework of secondary development in detail. If you fully understand the author's code, it is basically the same. Remember to change #include "PlayM4.h" to #include "plaympeg4.h", Hikvision's SDK has been updated

               http://blog.csdn.net/shangtao1989/article/details/50260661 

               This blog post is very important about converting YV12 to RGB. I suggest that you use the second method provided by the author to replace the method of converting YV12 to RGB in the first blog post. In addition, it is recommended that you open up two image spaces for conversion in advance. In this way, the real-time performance can be improved during the real-time callback process.

                My code is at the end of the article (non-computer students), I hope it will be useful to everyone. I will first give some problems encountered during this period and solutions, which may be clumsy.

                The first is the configuration problem. First, add the include directory and library directory according to the development document, and then add the HCNetSDK.lib;PlayCtrl.lib;ws2_32.lib;winmm.lib;GdiPlus.lib file in the linker-input-additional dependencies



Then compile the code, and two dll files may be missing. Note: If you are compiling in debug mode, add the corresponding files in the generated debug folder.

Take the original words from a development document:

1. When updating the device network SDK, the HCNetSDK.dll, HCCore.dll, PlayCtrl.dll, SuperRender.dll, AudioRender.dll, HCNetSDKCom folder and other files in the SDK development kit [Library File] should be loaded into the program.

  [HCNetSDKCom folder] (including the functional component dll library file) needs to be loaded together with HCNetSDK.dll and HCCore.dll, and placed in the same directory, and the HCNetSDKCom folder name cannot be modified.




Compile and debug again to run normally.

Then you will find that the playback is a bit stuck, generally there is a 5S delay, and even after running for a period of time, a lot of  PlayM4_InputData failed   will be printed and then an error happened error will be reported   .

The reason is stated in the SDK documentation:  Interfaces or operations that may take a long time cannot be performed in the callback function, and it is not recommended to call the interface of the SDK (HCNetSDK.dll) itself

Personally, I think it means that the time-consuming code cannot be run in the decoding callback function void CALLBACK DecCBFun (*******). If you don't believe me, just comment out imshow() and waitkey().

There are many solutions:

               1. You can try to use multi-threading to display in another thread.

               2. Run in realse mode, remember to add relevant files in the realse folder after compiling . (The running speed of realse mode is immediately improved, which can achieve real-time performance, and the CPU usage is greatly reduced)

               3. Log in to the IP camera system (the URL is the IP you changed by yourself), configure - reduce the resolution in video and audio (my default is 2560*1440, when I adjust it to 1280*720, it can also meet real-time performance in debug mode )

The above is basically the problem I encountered, and I'm just a noob, so don't laugh after reading it.


Finally, I give my own code, not a computer professional, I hope it will be useful to everyone.

#include <iostream>
#include "Windows.h"
#include "HCNetSDK.h"
#include "plaympeg4.h"
#include <opencv2\opencv.hpp>  
#include "cv.h"  
#include "highgui.h"


using namespace std;
using namespace cv;

int iPicNum = 0;//Set channel NO.  
LONG nPort = -1;
HWND hWnd = NULL;



//The decoded callback video is YUV data (YV12), and the audio is PCM data  
void CALLBACK DecCBFun(long nPort, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2)
{
	long lFrameType = pFrameInfo->nType;

	if (lFrameType == T_YV12)
	{
		Mat dst(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);//Height nHeight is 720, nWidth is 1280, 8UC3 means 8bit uchar unsigned type, 3 channel value
		Mat src(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (uchar*)pBuf);
		cvtColor(src, dst, CV_YUV2BGR_YV12);
 
		imshow("IPCamera", dst);
		waitKey(10);

		//At this time, the video data in YV12 format is stored in pBuf, which can be fwrite(pBuf,nSize,1,Videofile);  
		//fwrite(pBuf,nSize,1,fp);  
	}
	/***************
	else if (lFrameType ==T_AUDIO16)
	{
	//This is audio data, the data is stored in pBuf, you can fwrite(pBuf,nSize,1,Audiofile);

	}
	else
	{

	}
	*******************/

}

///Real-time stream callback  
void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)
{
	DWORD dRet = 0;
	BOOL inData = FALSE;
	switch (dwDataType)
	{
	case NET_DVR_SYSHEAD: //system header  
		if (nPort >= 0)
		{
			break; //The same code stream does not need to call the open stream interface multiple times
		}
		if (!PlayM4_GetPort(&nPort)) //Get the unused channel number of the playback library  
		{
			break;
		}
		if (dwBufSize > 0)
		{
			if (!PlayM4_SetStreamOpenMode(nPort, STREAME_REALTIME)) //Set the real-time stream playback mode
			{
				cout << "PlayM4_SetStreamOpenMode failed " << endl;
				break;
			}
			if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024 * 1024))   //查询
			{
				cout << "PlayM4_OpenStream failed " << endl;
				dRet = PlayM4_GetLastError(nPort);
				break;
			}
			//Set the decoding callback function to only decode but not display  
			if (!PlayM4_SetDecCallBack(nPort, DecCBFun)) //Query
			{
				dRet = PlayM4_GetLastError(nPort);
				break;
			}

			//Set the decoding callback function to decode and display  
			//if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))  
			//{  
			//  dRet=PlayM4_GetLastError(nPort);  
			//  break;  
			//}  

			//Open video decoding  
			if (!PlayM4_Play(nPort, hWnd))
			{
				dRet = PlayM4_GetLastError(nPort);
				break;
			}

			//Open audio decoding, the code stream needs to be a composite stream  
			/*if (!PlayM4_PlaySound(nPort))
			{
				dRet = PlayM4_GetLastError(nPort);
				break;
			}*/
		}
		break;

	case NET_DVR_STREAMDATA: //Stream data  
		inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
			while (!inData)
			{
				Sleep(10);
				inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
				cout << "PlayM4_InputData failed 11111" << endl;
				break;
			}
		break;
	default:
		inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
		while (!inData)
			{
				Sleep(10);
				inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
				cout << "PlayM4_InputData failed 22222" << endl;
				break;
			}
		break;
	}
}

void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
{
	char tempbuf[256] = { 0 };
	switch (dwType)
	{
	case EXCEPTION_RECONNECT: //Reconnect during preview  
		cout << "----------reconnect--------" << endl;
		break;
	default:
		break;
	}
}

void main()
{

	//---------------------------------------  
	// initialize  
	NET_DVR_Init();
	//Set the connection time and reconnection time  
	NET_DVR_SetConnectTime(2000, 1);
	NET_DVR_SetReconnect(10000, true);


	//---------------------------------------  
	// register the device  
	LONG lUserID;
	NET_DVR_USER_LOGIN_INFO struLoginInfo = { 0 };
	NET_DVR_DEVICEINFO_V40 struDeviceInfo = { 0 };

	strcpy((char *)struLoginInfo.sDeviceAddress, "192.168.xx"); //device IP address
	strcpy((char *)struLoginInfo.sUserName, "admin"); //Device login user name
	strcpy((char *)struLoginInfo.sPassword, "mima123456"); //Device login password
	struLoginInfo.wPort = 8000;
	struLoginInfo.bUseAsynLogin = 0; //Synchronous login, if the login interface returns successfully, the login is successful

	lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfo);
	if (lUserID < 0)
	{
		cout << "NET_DVR_Login_V40 failed, error code: " << NET_DVR_GetLastError() << endl;
		NET_DVR_Cleanup();
		return;
	}


	int iRet
	//Get the compression parameters of channel 1
	DWORD dwReturnLen;
	NET_DVR_COMPRESSIONCFG_V30 struParams = { 0 };
	iRet = NET_DVR_GetDVRConfig(lUserID, NET_DVR_GET_COMPRESSCFG_V30, 1, &struParams, \
		sizeof(NET_DVR_COMPRESSIONCFG_V30), &dwReturnLen);
	if (!iRet)
	{
		printf("NET_DVR_GetDVRConfig NET_DVR_GET_COMPRESSCFG_V30 error.\n");
		NET_DVR_Logout(lUserID);
		NET_DVR_Cleanup();
		return;
	}
	//Set the compression parameters of channel 1
	struParams.struNormHighRecordPara.dwVideoBitrate = 0.5;
	iRet = NET_DVR_SetDVRConfig(lUserID, NET_DVR_SET_COMPRESSCFG_V30, 1, \
		&struParams, sizeof(NET_DVR_COMPRESSIONCFG_V30));
	if (!iRet)
	{
		printf("NET_DVR_GetDVRConfig NET_DVR_SET_COMPRESSCFG_V30 error.\n");
		NET_DVR_Logout(lUserID);
		NET_DVR_Cleanup();
		return;
	}
	//Get the compression parameters of channel 1
	iRet = NET_DVR_GetDVRConfig(lUserID, NET_DVR_GET_COMPRESSCFG_V30, 1, \
		&struParams, sizeof(NET_DVR_COMPRESSIONCFG_V30), &dwReturnLen);
	if (!iRet)
	{
		printf("NET_DVR_GetDVRConfig NET_DVR_GET_COMPRESSCFG_V30 error.\n");
		NET_DVR_Logout(lUserID);
		NET_DVR_Cleanup();
		return;
	}
	printf("Video Bitrate is %d\n", struParams.struNormHighRecordPara.dwVideoBitrate);



	//---------------------------------------  
	//Set the exception message callback function  
	NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);


	NET_DVR_PREVIEWINFO StruPlayInfo = { 0 };
	StruPlayInfo.hPlayWnd = NULL; //The window is empty, the device SDK does not decode and only fetches the stream  
	StruPlayInfo.lChannel = 1; //Preview channel number
	StruPlayInfo.dwStreamType = 0; //0-mainstream code, 1-substream code, 2-stream code3, 3-stream code4, and so on
	StruPlayInfo.dwLinkMode = 0; //0-TCP mode, 1-UDP mode, 2-Multicast mode, 3-RTP mode, 4-RTP/RTSP, 5-RSTP/HTTP
	StruPlayInfo.bBlocked = 1; //0-non-blocking fetching, 1-blocking fetching


	LONG lRealPlayHandle;
	lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &StruPlayInfo, fRealDataCallBack, NULL);


	if (lRealPlayHandle<0)
	{
		cout << "NET_DVR_RealPlay_V40 failed! Error number:  " << NET_DVR_GetLastError() << endl;
		return;
	}
    
	cout << "The program is successful !!" << endl;
	Sleep(-1);

	//---------------------------------------  
	// close the preview  
	if (!NET_DVR_StopRealPlay(lRealPlayHandle))
	{
		cout << "NET_DVR_StopRealPlay error! Error number: " << NET_DVR_GetLastError() << endl;
		NET_DVR_Logout(lUserID);
		NET_DVR_Cleanup();
		return;
	}
	//log out the user  
	NET_DVR_Logout(lUserID);
	NET_DVR_Cleanup();

	return;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325433659&siteId=291194637