Unity3D開發之——海康威視攝像機SDK集成

這幾天整理了一下辦公電腦裏的開發工程,刪除了一些測試工程,也發現了之前做的有些比較還可以的測試Demo。
代碼工程上傳至鏈接:https://pan.baidu.com/s/13-rTaeVLtcX0KzHy2RT5Ow 提取碼:g0u2
我這裏用的海康威視的SDK是比較老了,因爲這個Demo是2017年做的。(注:我只是將海康威視的C#編寫的視頻監控集成到Unity3D中使用(我Unity用的5.5版本),使用的是CH-HCNetSDK(Windows64)V5.2.3.3_build20160623_2版本下載地址:鏈接:https://pan.baidu.com/s/1aMX-bM3h00ogvD53YhER6w
提取碼:o5y5 )
大家可以去海康威視下載最新的SDK,下載地址https://www.hikvision.com/cn/download_more_570.html#prettyPhoto
下載你需要的版本。
SDK下載完成後,你在Unity新建一個工程,按照下載SDK文件中找到Demo示例,找C#開發,裏面有需要的功能C# demo,打開你需要的Demo,裏面有一個說明,按照這個說明,找到.dll庫文件,導入Unity的Plugins文件中。
Unity3D開發之——海康威視攝像機SDK集成
其次,找到CHCNetSDK.cs文件和PlayCtrl.cs文件,去掉C#編輯界面的內容重新集成SDK主要功能。
Unity3D開發之——海康威視攝像機SDK集成
比如:
CHCNetSDK.cs
Unity3D開發之——海康威視攝像機SDK集成
PlayCtrl.cs
Unity3D開發之——海康威視攝像機SDK集成
再次,創建一個集成功能腳本工具,實現視頻監控功能。我粘主要功能代碼

        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;

                //初始化
                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);

                          //數據流
        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; //同一路碼流不需要多次調用開流接口
                        }

                        //獲取播放句柄 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 display buffer number
                        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
                        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 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;
            }
        }

                //回調視頻
                  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();
                }
            }
        }

        //視頻流轉換
        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;

                }
            }
        }

最後,創建自己的View層腳本,即可實現海康威視的SDK集成Unity3D 實現監控。親測可以,但是對視頻解碼這塊不太懂,出來的畫面有點色彩不太對,流暢度還可以。

注意:視頻色彩可在Yv12ToYUV和DecCallbackFUN方法中修改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章