千家信息网

C#中如何使用SDK解码回调函数DecCallbackFUN()

发表于:2024-09-30 作者:千家信息网编辑
千家信息网最后更新 2024年09月30日,这篇文章主要介绍C#中如何使用SDK解码回调函数DecCallbackFUN(),文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!代码1、摄像头操作代码 struct Cam
千家信息网最后更新 2024年09月30日C#中如何使用SDK解码回调函数DecCallbackFUN()

这篇文章主要介绍C#中如何使用SDK解码回调函数DecCallbackFUN(),文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

代码

1、摄像头操作代码
    struct CameraInfo    {        public string strIP;        public short nPort;        public string strUserName;        public string strPassword;    }    class IDeviceCamera    {        public Image m_img = null;        public virtual bool InitCamera( CameraInfo stInfo )        {            return true;        }    }        class DeviceCamera : IDeviceCamera    {        private CameraInfo m_stCameraInfo;        private bool m_bInitSDK = false;        private Int32 m_lUserID = -1;        private Int32 m_lRealHandle = -1;        private Int32 m_lPort = -1;        CHCNetSDK.REALDATACALLBACK RealData = null; //必须得定义为成员变量        public override bool InitCamera( CameraInfo stInfo )        {            m_stCameraInfo = stInfo;            m_bInitSDK = CHCNetSDK.NET_DVR_Init();            if ( !m_bInitSDK )            {                uint nError = CHCNetSDK.NET_DVR_GetLastError();            }            CHCNetSDK.NET_DVR_SetConnectTime( 5000, 1 );            CHCNetSDK.NET_DVR_SetReconnect( 10000, 1 );            if ( m_bInitSDK == false )            {                MessageBox.Show( "NET_DVR_Init error!" );                return false;            }            else            {                //保存SDK日志 To save the SDK log                CHCNetSDK.NET_DVR_SetLogToFile( 3, "C:\\SdkLog\\", true );            }            string DVRIPAddress = stInfo.strIP;     //设备IP地址或者域名 Device IP            Int16 DVRPortNumber = stInfo.nPort;     //设备服务端口号 Device Port            string DVRUserName = stInfo.strUserName;//设备登录用户名 User name to login            string DVRPassword = stInfo.strPassword;//设备登录密码 Password to login            CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30();            m_lUserID = CHCNetSDK.NET_DVR_Login_V30( DVRIPAddress, DVRPortNumber, DVRUserName, DVRPassword, ref DeviceInfo );            if ( m_lUserID < 0 )            {                MessageBox.Show( "登录失败!" );                CHCNetSDK.NET_DVR_Cleanup();                return false;            }            //            CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();            lpPreviewInfo.hPlayWnd = (IntPtr)null;            lpPreviewInfo.lChannel = 1;            lpPreviewInfo.dwStreamType = 0;       //码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推            lpPreviewInfo.dwLinkMode = 0;         //连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP             lpPreviewInfo.bBlocked = true;        //0- 非阻塞取流,1- 阻塞取流            lpPreviewInfo.dwDisplayBufNum = 15;   //播放库播放缓冲区最大缓冲帧数            //使用回调函数取摄像头数据            RealData = new CHCNetSDK.REALDATACALLBACK( RealDataCallBack );//预览实时流回调函数            IntPtr pUser = new IntPtr();//用户数据            m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40( m_lUserID, ref lpPreviewInfo, RealData, pUser );            CHCNetSDK.NET_DVR_RigisterDrawFun( m_lRealHandle, new CHCNetSDK.DRAWFUN( cbDrawFun ), 0 );//回调函数:绘制图标            return true;        }        private uint nLastErr = 0;        private static PlayCtrl.DECCBFUN m_fDisplayFun = null;        private IntPtr m_ptrRealHandle;        public void RealDataCallBack( Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser )        {            //下面数据处理建议使用委托的方式            switch ( dwDataType )            {                case CHCNetSDK.NET_DVR_SYSHEAD:     // sys head                    if ( dwBufSize > 0 )                    {                        if ( m_lPort >= 0 )                            return; //同一路码流不需要多次调用开流接口                        //获取播放句柄 Get the port to play                        if ( !PlayCtrl.PlayM4_GetPort( ref m_lPort ) )                        {                            nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );                            break;                        }                        //设置流播放模式 Set the stream mode: real-time stream mode                        if ( !PlayCtrl.PlayM4_SetStreamOpenMode( m_lPort, PlayCtrl.STREAME_REALTIME ) )                        {                            nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );                            //str = "Set STREAME_REALTIME mode failed, error code= " + nLastErr;                            //this.BeginInvoke( AlarmInfo, str );                        }                        //打开码流,送入头数据 Open stream                        if ( !PlayCtrl.PlayM4_OpenStream( m_lPort, pBuffer, dwBufSize, 2 * 1024 * 1024 ) )                        {                            nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );                            //str = "PlayM4_OpenStream failed, error code= " + nLastErr;                            //this.BeginInvoke( AlarmInfo, str );                            break;                        }                        //设置显示缓冲区个数 Set the display buffer number                        if ( !PlayCtrl.PlayM4_SetDisplayBuf( m_lPort, 15 ) )                        {                            nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );                            //str = "PlayM4_SetDisplayBuf failed, error code= " + nLastErr;                            //this.BeginInvoke( AlarmInfo, str );                        }                        //设置显示模式 Set the display mode                        //if ( !PlayCtrl.PlayM4_SetOverlayMode( m_lPort, 0, 0) ) //play off screen                         //{                        //    nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );                        //    //str = "PlayM4_SetOverlayMode failed, error code= " + nLastErr;                        //    //this.BeginInvoke( AlarmInfo, str );                        //}                        //设置解码回调函数,获取解码后音视频原始数据 Set callback function of decoded data                        m_fDisplayFun = new PlayCtrl.DECCBFUN( DecCallbackFUN );                        if ( !PlayCtrl.PlayM4_SetDecCallBackEx( m_lPort, m_fDisplayFun, IntPtr.Zero, 0 ) )                        {                            //this.BeginInvoke( AlarmInfo, "PlayM4_SetDisplayCallBack fail" );                        }                        //开始解码 Start to play                                               if ( !PlayCtrl.PlayM4_Play( m_lPort, m_ptrRealHandle ) )                        {                            nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );                            //str = "PlayM4_Play failed, error code= " + nLastErr;                            //this.BeginInvoke( AlarmInfo, str );                            break;                        }                    }                    break;                case CHCNetSDK.NET_DVR_STREAMDATA: // video stream data                default: //the other data                    if ( dwBufSize > 0 && m_lPort != -1 )                    {                        for ( int i = 0; i < 999; i++ )                        {                            //送入码流数据进行解码 Input the stream data to decode                            if ( !PlayCtrl.PlayM4_InputData( m_lPort, pBuffer, dwBufSize ) )                            {                                nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );                                //str = "PlayM4_InputData failed, error code= " + nLastErr;                                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            {                byte[] byteBuffYV12 = new byte[ nSize ];                Marshal.Copy( pBuf, byteBuffYV12, 0, nSize );                long lRGBSize = (long)pFrameInfo.nWidth * pFrameInfo.nHeight * 4;                byte[] bufferRGB32 = new byte[ lRGBSize ];                CommonFun.YV12_to_RGB32( byteBuffYV12, bufferRGB32, pFrameInfo.nWidth, pFrameInfo.nHeight );                byteBuffYV12 = null;                Bitmap bmpFromGRB32 = CommonFun.RGB32_to_Image( bufferRGB32, pFrameInfo.nWidth, pFrameInfo.nHeight );                bufferRGB32 = null;                if ( null == bmpFromGRB32 )                    return;                m_img = bmpFromGRB32;            }        }    }

注:得到的m_img用于PictureBox进行显示。

2、YV12转换为RGB32、RGB32转换为Image代码
class CommonFun    {        public static bool YV12_to_RGB32(  byte[] buffYV12, byte[] bufferRGB32, int nWidth, int nHeight )        {            if( buffYV12.Length < 0 || bufferRGB32.Length < 0 )                return false;            long nYLen = (long)nWidth * nHeight;            int nHfWidth = ( nWidth >> 1 );            if ( nYLen < 1 || nHfWidth < 1 )                return false;            byte[] byteYData = buffYV12.Skip( 0 ).Take( nWidth*nHeight ).ToArray();            byte[] byteUData = buffYV12.Skip( nWidth*nHeight ).Take( (nHeight/2)*(nWidth/2) ).ToArray();            byte[] byteVData = buffYV12.Skip( nWidth*nHeight + (nHeight/2)*(nWidth/2) ).Take( (nHeight/2)*(nWidth/2) ).ToArray();            if ( byteYData.Length < 0 || byteVData.Length < 0 || byteUData.Length < 0 )                return false;            int[] nRgb = new int[4];            for( int nRow = 0; nRow < nHeight; nRow++ )            {                for( int nCol = 0; nCol < nWidth; nCol++ )                {                    int Y = byteYData[nRow*nWidth + nCol];                    int U = byteUData[(nRow / 2)*(nWidth / 2) + (nCol / 2)];                    int V = byteVData[(nRow / 2)*(nWidth / 2) + (nCol / 2)];                    int R = Y + (U - 128) + (((U - 128) * 103) >> 8);                    int G = Y - (((V - 128) * 88) >> 8) - (((U - 128) * 183) >> 8);                    int B = Y + (V - 128) + (((V - 128) * 198) >> 8);                    // r分量值                     R = R<0 ? 0 : R;                    nRgb[2] = R > 255 ? 255 : R;                    // g分量值                    G = G<0 ? 0 : G;                    nRgb[1] = G > 255 ? 255 : G;                    // b分量值                     B = B<0 ? 0 : B;                    nRgb[0] = B > 255 ? 255 : B;                    //A分量值                    nRgb[ 3 ] = 255;                    //Out RGB Buffer                    bufferRGB32[4 * (nRow*nWidth + nCol) + 0] = (byte)nRgb[0];                    bufferRGB32[4 * (nRow*nWidth + nCol) + 1] = (byte)nRgb[1];                    bufferRGB32[4 * (nRow*nWidth + nCol) + 2] = (byte)nRgb[2];                    bufferRGB32[4 * (nRow*nWidth + nCol) + 3] = (byte)nRgb[3];                }            }            return true;        }        public static Bitmap RGB32_to_Image( byte[] byteBuff, int nWidth, int nHeight )        {            if ( byteBuff.Length <= 0 || byteBuff.Length < nWidth*nHeight )                return null;            Bitmap bmp = new Bitmap( nWidth, nHeight, PixelFormat.Format32bppArgb );            //锁定内存数据            BitmapData bmpData = bmp.LockBits( new Rectangle( 0, 0, nWidth, nHeight ), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb );            //输入颜色数据            System.Runtime.InteropServices.Marshal.Copy( byteBuff, 0, bmpData.Scan0, byteBuff.Length );            //解锁            bmp.UnlockBits( bmpData );            return bmp;        }    }

以上是"C#中如何使用SDK解码回调函数DecCallbackFUN()"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

0