C# 海康威视网络半球摄像头回调YV12取画面
海康网络摄像头回调取画面,网口最好用千兆的网卡来做,开始用笔记本的百兆网口,不管怎么优化都是卡顿的,
后来用千兆网卡台式机的,基本就没有卡顿了,取图再加上运动检测处理,基本上十几毫秒每帧。
用回调方式处理数据流方式,参见官方的Demo,本文只介绍相关的回调YV12取图,回调中的图像数据是庞大的,
在回调中只适合做简单的处理,如果处理过于复杂,会出现卡顿的现象。因为我只需要对图像进行运动检测处理,所以只是
简单取了图像的灰度图,具体如下:
//回调函数
private void DecCallbackFUN(int nPort, IntPtr pBuf, int nSize, ref PlayCtrl.FRAME_INFO pFrameInfo, int nReserved1, int nReserved2) { // 将pBuf解码后视频输入写入文件中(解码后YUV数据量极大,尤其是高清码流,不建议在回调函数中处理) if (pFrameInfo.nType == 3) //#define T_YV12 3 { int m_Width = pFrameInfo.nWidth; int m_Height = pFrameInfo.nHeight; //this.MeasureTime(() => { var img = GetBitmapFromYV12(pBuf, m_Width, m_Height, nSize); NewFrame?.Invoke((Bitmap)img.Clone()); img.Dispose(); // }); } }
///把YV12数据转为BGR24数据,我只关心灰度图,因此只取了Y数据,如果想获取彩色图像,考虑计算UV数据
private unsafe bool YV12ToBGR24(byte* pYUV, byte* pBGR24, int width, int height) { if (width < 1 || height < 1 || pYUV == null || pBGR24 == null) return false; byte* yData = pYUV; int yIdx; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { yIdx = i * width + j; pBGR24[yIdx * 3] = pBGR24[yIdx * 3 + 1] = pBGR24[yIdx * 3 + 2] = yData[yIdx]; } } return true; }
///获取回调的图片
private unsafe Bitmap GetBitmapFromYV12(IntPtr pBuf, int width, int height, int nSize) { Bitmap bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, bitmap.PixelFormat); byte* desPtr = (byte*)bmpData.Scan0; byte* srcPtr = (byte*)pBuf; YV12ToBGR24(srcPtr, desPtr, width, height); bitmap.UnlockBits(bmpData); return bitmap; }