这几天整理了一下办公电脑里的开发工程,删除了一些测试工程,也发现了之前做的有些比较还可以的测试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集成_第1张图片
其次,找到CHCNetSDK.cs文件和PlayCtrl.cs文件,去掉C#编辑界面的内容重新集成SDK主要功能。
Unity3D开发之——海康威视摄像机SDK集成_第2张图片
比如:
CHCNetSDK.cs
Unity3D开发之——海康威视摄像机SDK集成_第3张图片
PlayCtrl.cs
Unity3D开发之——海康威视摄像机SDK集成_第4张图片
再次,创建一个集成功能脚本工具,实现视频监控功能。我粘主要功能代码

        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().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().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方法中修改。