How to use SDK to decode the callback function DecCallbackFUN () in C #
This article mainly introduces how to use the SDK decoding callback function DecCallbackFUN () in C#. It is very detailed and has certain reference value. Interested friends must read it!
Code 1, camera operation code 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; / / must be defined as a member variable 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 {/ / Save SDK log To save the SDK log CHCNetSDK.NET_DVR_SetLogToFile (3, "C:\\ SdkLog\", true) } string DVRIPAddress = stInfo.strIP; / / device IP address or domain name Device IP Int16 DVRPortNumber = stInfo.nPort; / / device service port number Device Port string DVRUserName = stInfo.strUserName;// device login user name User name to login string DVRPassword = stInfo.strPassword / / device login password 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 / / the same bitstream does not need to call the open stream API multiple times / / get the playback handle Get the port to play if (! PlayCtrl.PlayM4_GetPort (ref m_lPort)) {nLastErr = PlayCtrl.PlayM4_GetLastError (m_lPort); break } / / set stream playback mode 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 the code stream and send the header data 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 number of display buffers 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 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 the decoding callback function to obtain the decoded audio / video raw data 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 decoding 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-((V12888) > > 8)-((U128x183) > > 8); int B = Y + (V128x198) > 8); / / r component value R = R 255255: r / / g component value G = G 255255: G; / b component value B = B 255255: B; / / A component value nRgb [3] = 255i / / 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)