Unity3D Development -- Hikvision camera SDK integration

In recent days, I have sorted out the development projects in the office computer, deleted some test projects, and found that some of the test Demo that I have done before can still be used.
Code engineering upload to link: https://pan.baidu.com/s/13-rTaeVLtcX0KzHy2RT5Ow Extraction code: g0u2
The SDK of Hikvision that I use here is relatively old, because this Demo was made in 2017. (Note: I just integrated the video monitoring written by C of Hikvision into Unity3D (version 5.5 used by Unity), using ch-hcnetsdk (windows64) v5.2.3.3 ﹐ build20160623 ﹐ 2 download address: link: https://pan.baidu.com/s/1aMX-bM3h00ogvD53YhER6w
Extraction code: o5y5)
You can go to Hikvision to download the latest SDK at https://www.hikvision.com/cn/download'more'570.html'prettyphoto
Download the version you need.
After the SDK download is completed, you can create a new project in Unity. Follow the Demo example in the download SDK file, find C ා development, which has the required function C ා Demo, open the Demo you need, and there is a description in it. Follow the description, find the. dll library file, and import it into the Plugins file of Unity.

Secondly, find the CHCNetSDK.cs file and PlayCtrl.cs file, remove the content of the C ා editing interface and re integrate the main functions of the SDK.

For example:
CHCNetSDK.cs

PlayCtrl.cs

Thirdly, create an integrated function script tool to realize the video monitoring function. I stick the main function code

        private uint iLastErr = 0;
        private int m_lUserID = -1;
        private bool m_bInitSDK = false;
        private bool m_bRecord = false;
        private int m_lRealHandle = -1;
        private string str;
        private int m_lPort = -1;

                  Texture2D img;
        private string move_url;
        private FileInfo file;
        private byte[] buffer_byte;
        Texture2D tex;

        private int buffer_count = 0;
        private int num = 0;

        private PlayCtrl.DECCBFUN m_fDisplayFun = null;
        byte[] byteBuf;
        byte[] outYuv;

                //initialization
                void Init()
                {
                 tex = new Texture2D(2560, 1440, TextureFormat.ATC_RGBA8, false);
            m_bInitSDK = CHCNetSDK.NET_DVR_Init();
            if (!m_bInitSDK)
                Debug.Log("NET_DVR_Init error!");
            else
                CHCNetSDK.NET_DVR_SetLogToFile(3, "D:\\SdkLog\\", true);

            // Create a texture. Texture size does not matter, since
            // LoadImage will replace with with incoming image size.
            Texture2D texe= new Texture2D(2, 2);
            // A small 64x64 Unity logo encoded into a PNG.
            byte[] nn = new byte[] { 0, 78, 3, 56, 128 };
            byte[] pngBytes = new byte[] {
            0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52,
            0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x08,0x00,0x00,0x00,0x00,0x8F,0x02,0x2E,
            0x02,0x00,0x00,0x01,0x57,0x49,0x44,0x41,0x54,0x78,0x01,0xA5,0x57,0xD1,0xAD,0xC4,
            0x30,0x08,0x83,0x81,0x32,0x4A,0x66,0xC9,0x36,0x99,0x85,0x45,0xBC,0x4E,0x74,0xBD,
            0x8F,0x9E,0x5B,0xD4,0xE8,0xF1,0x6A,0x7F,0xDD,0x29,0xB2,0x55,0x0C,0x24,0x60,0xEB,
            0x0D,0x30,0xE7,0xF9,0xF3,0x85,0x40,0x74,0x3F,0xF0,0x52,0x00,0xC3,0x0F,0xBC,0x14,
            0xC0,0xF4,0x0B,0xF0,0x3F,0x01,0x44,0xF3,0x3B,0x3A,0x05,0x8A,0x41,0x67,0x14,0x05,
            0x18,0x74,0x06,0x4A,0x02,0xBE,0x47,0x54,0x04,0x86,0xEF,0xD1,0x0A,0x02,0xF0,0x84,
            0xD9,0x9D,0x28,0x08,0xDC,0x9C,0x1F,0x48,0x21,0xE1,0x4F,0x01,0xDC,0xC9,0x07,0xC2,
            0x2F,0x98,0x49,0x60,0xE7,0x60,0xC7,0xCE,0xD3,0x9D,0x00,0x22,0x02,0x07,0xFA,0x41,
            0x8E,0x27,0x4F,0x31,0x37,0x02,0xF9,0xC3,0xF1,0x7C,0xD2,0x16,0x2E,0xE7,0xB6,0xE5,
            0xB7,0x9D,0xA7,0xBF,0x50,0x06,0x05,0x4A,0x7C,0xD0,0x3B,0x4A,0x2D,0x2B,0xF3,0x97,
            0x93,0x35,0x77,0x02,0xB8,0x3A,0x9C,0x30,0x2F,0x81,0x83,0xD5,0x6C,0x55,0xFE,0xBA,
            0x7D,0x19,0x5B,0xDA,0xAA,0xFC,0xCE,0x0F,0xE0,0xBF,0x53,0xA0,0xC0,0x07,0x8D,0xFF,
            0x82,0x89,0xB4,0x1A,0x7F,0xE5,0xA3,0x5F,0x46,0xAC,0xC6,0x0F,0xBA,0x96,0x1C,0xB1,
            0x12,0x7F,0xE5,0x33,0x26,0xD2,0x4A,0xFC,0x41,0x07,0xB3,0x09,0x56,0xE1,0xE3,0xA1,
            0xB8,0xCE,0x3C,0x5A,0x81,0xBF,0xDA,0x43,0x73,0x75,0xA6,0x71,0xDB,0x7F,0x0F,0x29,
            0x24,0x82,0x95,0x08,0xAF,0x21,0xC9,0x9E,0xBD,0x50,0xE6,0x47,0x12,0x38,0xEF,0x03,
            0x78,0x11,0x2B,0x61,0xB4,0xA5,0x0B,0xE8,0x21,0xE8,0x26,0xEA,0x69,0xAC,0x17,0x12,
            0x0F,0x73,0x21,0x29,0xA5,0x2C,0x37,0x93,0xDE,0xCE,0xFA,0x85,0xA2,0x5F,0x69,0xFA,
            0xA5,0xAA,0x5F,0xEB,0xFA,0xC3,0xA2,0x3F,0x6D,0xFA,0xE3,0xAA,0x3F,0xEF,0xFA,0x80,
            0xA1,0x8F,0x38,0x04,0xE2,0x8B,0xD7,0x43,0x96,0x3E,0xE6,0xE9,0x83,0x26,0xE1,0xC2,
            0xA8,0x2B,0x0C,0xDB,0xC2,0xB8,0x2F,0x2C,0x1C,0xC2,0xCA,0x23,0x2D,0x5D,0xFA,0xDA,
            0xA7,0x2F,0x9E,0xFA,0xEA,0xAB,0x2F,0xDF,0xF2,0xFA,0xFF,0x01,0x1A,0x18,0x53,0x83,
            0xC1,0x4E,0x14,0x1B,0x00,0x00,0x00,0x00,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82,};
            // Load data into the texture.
            texe.LoadImage(pngBytes);

                          //data stream
        public void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser)
        {
            Debug.Log("dwDataType   " + dwDataType + "pBuffer    " + pBuffer + "dwBufSize      " + dwBufSize);
            //byte[] bte = new byte[(int)dwBufSize];
            switch (dwDataType)
            {
                case CHCNetSDK.NET_DVR_SYSHEAD:
                    if (dwBufSize > 0)
                    {
                        //Marshal.Copy(pBuffer, bte, 0, (int)dwBufSize);

                        //for (int i = 0; i < bte.Length; i++)
                        //{
                        //    buffer_byte[num + i] = bte[i];
                        //}
                        //num += bte.Length;

                        if (m_lPort >= 0)
                        {
                            return; //The same code stream does not need to call the open stream interface multiple times
                        }

                        //Get the port to play
                        if (!PlayCtrl.PlayM4_GetPort(ref m_lPort))
                        {
                            iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                            str = "PlayM4_GetPort failed, error code= " + iLastErr;
                            Debug.Log(str);
                            break;
                        }

                        //Set the stream mode: real time stream mode
                        if (!PlayCtrl.PlayM4_SetStreamOpenMode(m_lPort, PlayCtrl.STREAME_REALTIME))
                        {
                            iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                            str = "Set STREAME_REALTIME mode failed, error code= " + iLastErr;
                            Debug.Log(str);
                        }

                        //Open stream
                        if (!PlayCtrl.PlayM4_OpenStream(m_lPort, pBuffer, dwBufSize, 2 * 1024 * 1024))
                        {
                            iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                            str = "PlayM4_OpenStream failed, error code= " + iLastErr;
                            Debug.Log(str);
                            break;
                        }

                        //Set the number of display buffer
                        if (!PlayCtrl.PlayM4_SetDisplayBuf(m_lPort, 15))
                        {
                            iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                            str = "PlayM4_SetDisplayBuf failed, error code= " + iLastErr;
                            Debug.Log(str);
                        }

                        //Set the display mode set the display mode
                        if (!PlayCtrl.PlayM4_SetOverlayMode(m_lPort, 0, 0/* COLORREF(0)*/)) //play off screen 
                        {
                            iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                            str = "PlayM4_SetOverlayMode failed, error code= " + iLastErr;
                            Debug.Log(str);
                        }

                        //Set decoding callback function of decoded data
                        m_fDisplayFun = new PlayCtrl.DECCBFUN(DecCallbackFUN);

                        //if (!PlayCtrl.PlayM4_SetDecCallBackEx(m_lPort, m_fDisplayFun, IntPtr.Zero, 0))
                        //{
                        //    Debug.Log("PlayM4_SetDisplayCallBack fail");  
                        //}

                        PlayCtrl.PlayM4_SetDecCallBack(m_lPort , DecCallbackFUN);
                        ////Start to play                       
                        if (!PlayCtrl.PlayM4_Play(m_lPort,IntPtr.Zero))
                        {
                            iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                            str = "PlayM4_Play failed, error code= " + iLastErr;
                            Debug.Log(str);
                            break;
                        }

                    }
                    break;
                case CHCNetSDK.NET_DVR_STREAMDATA:

                    //Debug.Log("pBuffer" + pBuffer);
                    if (dwBufSize > 0 && m_lPort != -1)
                    {
                        //Marshal.Copy(pBuffer, bte, 0, (int)dwBufSize);
                        //for (int i = 0; i < bte.Length; i++)
                        //{
                        //    buffer_byte[num + i] = bte[i];
                        //    //Debug.Log("byteeeee  " + buffer_byte[i]);
                        //}
                        //num += bte.Length;

                        //buffer_count = num;
                        //img.LoadImage(buffer_byte);

                        //RawImg.GetComponent<RawImage>().texture = byteArrayToImage;
                        //Creat(byt);    
                        for (int i = 0; i < 999; i++)
                        {
                            //Input the stream data to decode
                            if (!PlayCtrl.PlayM4_InputData(m_lPort, pBuffer, dwBufSize))
                            {
                                iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                                str = "PlayM4_InputData failed, error code= " + iLastErr;
                                Thread.Sleep(2);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    break;
                default:
                    if (dwBufSize > 0 && m_lPort != -1)
                    {
                        //Input the other data
                        for (int i = 0; i < 999; i++)
                        {
                            if (!PlayCtrl.PlayM4_InputData(m_lPort, pBuffer, dwBufSize))
                            {
                                iLastErr = PlayCtrl.PlayM4_GetLastError(m_lPort);
                                str = "PlayM4_InputData failed, error code= " + iLastErr;
                                Thread.Sleep(2);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    break;
            }
        }

                //Callback video
                  private void DecCallbackFUN(int nPort, IntPtr pBuf, int nSize, ref PlayCtrl.FRAME_INFO pFrameInfo, int nReserved1, int nReserved2)
        {
            if (pFrameInfo.nType == 3) //#define T_YV12 3
            {
                FileStream fs = null;
                BinaryWriter bw = null;
                try
                {
                    fs = new FileStream("DecodedVideo.yuv", FileMode.Append);
                    bw = new BinaryWriter(fs);
                    Marshal.Copy(pBuf, byteBuf, 0, byteBuf.Length);
                    Yv12ToYUV(byteBuf, pFrameInfo.nWidth, pFrameInfo.nHeight, 7680);

                    //for (int i = 0; i < byteBuf.Length; i++)
                    //{
                    //    Debug.Log("byteBuf  SSSSSS" + byteBuf[i]);
                    //}
                    //tex.LoadRawTextureData(byteBuf);
                    //tex.Apply();
                    //RawImg.GetComponent<RawImage>().texture = tex;
                    //Creat(byteBuf);

                }
                catch (System.Exception ex)
                {
                    Debug.Log(ex.ToString());
                }
                finally
                {
                    bw.Close();
                    fs.Close();
                }
            }
        }

        //Video stream conversion
        private void Yv12ToYUV(byte[] inYv12 ,int width,int height,int widthStep)
        {
            int col;
            int row;
            int tmp;
            int idx;

            int Y, U, V;   

            for (row = 0; row < height; row++)
            {
                idx = row * widthStep;
                int rowptr = row * width;
                for (col = 0; col < width; col++)
                {
                    tmp = (row / 2) * (width / 2) + (col / 2);

                    Y = ( int) inYv12[row * width + col];
                    U = ( int) inYv12[width * height + width * height / 4 + tmp];
                    V = ( int) inYv12[width * height + tmp];

                    outYuv[idx + col * 3] = (byte)Y;
                    outYuv[idx + col * 3 + 1] = (byte)U;
                    outYuv[idx + col * 3 + 2] = (byte)V;

                }
            }
        }

Finally, create your own View layer script to realize the monitoring of Hikvision's SDK integration Unity3D. It's OK to test by hand, but I don't know much about video decoding. The color of the picture is not right, and the fluency is OK.

Note: video color can be modified in Yv12ToYUV and DecCallbackFUN methods.

Tags: Programming SDK Unity

Posted on Mon, 18 May 2020 06:29:13 -0400 by siefkencp