Open CV学习记录(十三)——HcVision码流
来源:互联网 发布:淘宝华佗大药房旗舰店 编辑:程序博客网 时间:2024/05/29 02:31
#include <cstdio> #include <cstring> #include <iostream> #include "Windows.h" #include "HCNetSDK.h" #include "PlayM4.h" #include <opencv2\opencv.hpp> #include "cv.h" #include "highgui.h" #include <time.h> #define USECOLOR 1 using namespace std;using namespace std;//-------------------------------------------- int iPicNum = 0;//Set channel NO. LONG nPort = -1;HWND hWnd = NULL;/*widthStep表示存储一行像素需要的字节数。widthStep必须是4的倍数,如果8U图像宽度为3,那么widthStep是4,加一个字节补齐。这个图像的一行需要4个字节,只使用前3个,最后一个空在那儿不用。也就是一个宽3高3的图像的imageData数据大小为4*3=12字节。如果32F的图像,那么widthStep=width*4。*/void yv12toYUV(char *outYuv, char *inYv12, int width, int height, int widthStep){ int col, row; unsigned int Y, U, V; int tmp; int idx; //printf("widthStep=%d.\n",widthStep); for (row = 0; row<height; row++) { idx = row * widthStep; int rowptr = row*width; for (col = 0; col<width; col++) { //int colhalf=col>>1; tmp = (row / 2)*(width / 2) + (col / 2); // if((row==1)&&( col>=1400 &&col<=1600)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("row*width+col=%d,width*height+width*height/4+tmp=%d,width*height+tmp=%d.\n",row*width+col,width*height+width*height/4+tmp,width*height+tmp); // } Y = (unsigned int)inYv12[row*width + col]; U = (unsigned int)inYv12[width*height + width*height / 4 + tmp]; V = (unsigned int)inYv12[width*height + tmp]; // if ((col==200)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp); // return ; // } if ((idx + col * 3 + 2)> (1200 * widthStep)) { //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2); } outYuv[idx + col * 3] = Y; outYuv[idx + col * 3 + 1] = U; outYuv[idx + col * 3 + 2] = V; } } //printf("col=%d,row=%d.\n",col,row); }//解码回调 视频为YUV数据(YV12),音频为PCM数据 //回调函数对实时流进行处理 可输出 RGB32帧、YUV12帧void CALLBACK DecCBFun(long nPort, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2){ //only use *pBuf and pFrameInfo long lFrameType = pFrameInfo->nType; if (lFrameType == T_YV12) {#if USECOLOR //int start = clock(); IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3);//得到图像的Y分量 //IplImage* cvCreateImage( CvSize size, int depth, int channels );新建一张图像 yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth, pFrameInfo->nHeight, pImgYCrCb->widthStep);//得到全部RGB图像 ???yv12toYUV,yuv12(pBuf)->YUV(pImgYCrCb) //void yv12toYUV(char *outYuv, char *inYv12, int width, int height, int widthStep) IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3); cvCvtColor(pImgYCrCb, pImg, CV_YCrCb2RGB);//YUV(pImgYCrCb) to RGB(pImg) /* YCrCb即YUV,主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。 与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。 其中“Y”表示明亮度,也就是灰阶值;而“U”和“V” 表示的则是色度,作用是描述影像色彩及饱和度,用于指定像素的颜色。 “亮度”是透过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。 “色度”则定义了颜色的两个方面─色调与饱和度,分别用Cr和Cb来表示。 其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。 而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。 */ //int end = clock(); #else IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 1); memcpy(pImg->imageData, pBuf, pFrameInfo->nWidth*pFrameInfo->nHeight);#endif //printf("%d\n",end-start); cvShowImage("IPCamera", pImg); cvWaitKey(1);#if USECOLOR cvReleaseImage(&pImgYCrCb); cvReleaseImage(&pImg);#else cvReleaseImage(&pImg);#endif //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile); //fwrite(pBuf,nSize,1,fp); } /*************** else if (lFrameType ==T_AUDIO16) { //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); } else { } *******************/}///实时流回调 void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser){ DWORD dRet; switch (dwDataType) { case NET_DVR_SYSHEAD: //系统头 if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号 //LONG nPort = -1;全局变量 { break; } if (dwBufSize > 0) { if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024 * 1024))//打开流接口 { dRet = PlayM4_GetLastError(nPort); break; } //设置解码回调函数 只解码不显示 if (!PlayM4_SetDecCallBack(nPort, DecCBFun))//执行回调 { dRet = PlayM4_GetLastError(nPort); break; } //设置解码回调函数 解码且显示 //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL)) //{ // dRet=PlayM4_GetLastError(nPort); // break; //} //打开视频解码 if (!PlayM4_Play(nPort, hWnd)) { dRet = PlayM4_GetLastError(nPort); break; } //打开音频解码, 需要码流是复合流 if (!PlayM4_PlaySound(nPort)) { dRet = PlayM4_GetLastError(nPort); break; } } break; case NET_DVR_STREAMDATA: //码流数据 if (dwBufSize > 0 && nPort != -1) { BOOL inData = PlayM4_InputData(nPort, pBuffer, dwBufSize); while (!inData) { Sleep(10); inData = PlayM4_InputData(nPort, pBuffer, dwBufSize); OutputDebugString(L"PlayM4_InputData failed \n"); } } break; }}void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser){ char tempbuf[256] = { 0 }; switch (dwType) { case EXCEPTION_RECONNECT: //预览时重连 printf("----------reconnect--------%d\n", time(NULL)); break; default: break; }}void main() { //--------------------------------------- // 初始化 NET_DVR_Init(); //设置连接时间与重连时间 NET_DVR_SetConnectTime(2000, 1); NET_DVR_SetReconnect(10000, true); //--------------------------------------- // 获取控制台窗口句柄 //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32"); //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow"); //--------------------------------------- // 注册设备 LONG lUserID; NET_DVR_DEVICEINFO_V30 struDeviceInfo;//NET_DVR_DEVICEINFO_V30 设备参数结构体。 lUserID = NET_DVR_Login_V30("10.102.7.88", 8000, "admin", "12345", &struDeviceInfo); if (lUserID < 0) { printf("Login error, %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return; } //--------------------------------------- //设置异常消息回调函数 NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL); //cvNamedWindow("IPCamera"); //--------------------------------------- //启动预览并设置回调数据流 NET_DVR_CLIENTINFO ClientInfo;//预览参数结构体。 ClientInfo.lChannel = 1; //Channel number 设备通道号 ClientInfo.hPlayWnd = NULL; //窗口为空,设备SDK不解码只取流 //播放窗口的句柄,为NULL表示不显示图像 ClientInfo.lLinkMode = 0; //Main Stream ClientInfo.sMultiCastIP = NULL;//多播组地址 LONG lRealPlayHandle; lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, NULL, TRUE); if (lRealPlayHandle<0) { printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n", NET_DVR_GetLastError()); return; } //cvWaitKey(0); Sleep(-1); //fclose(fp); //--------------------------------------- //关闭预览 if (!NET_DVR_StopRealPlay(lRealPlayHandle)) { printf("NET_DVR_StopRealPlay error! Error number: %d\n", NET_DVR_GetLastError()); return; } //注销用户 NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); return;}
0 0
- Open CV学习记录(十三)——HcVision码流
- Open CV学习记录(十二)——HCvision IPC 利用NET_DVR_CaptureJPEGPicture_NEW进行视频抓图
- Open CV学习记录(二十三)——相机校准和立体匹配
- Open CV学习记录(八)——remap
- Open CV学习记录(十九)—图片拼接
- Open CV 学习记录(一)
- Open CV学习记录(十)
- Open CV学习记录(十一)
- Open CV学习记录(二)——图像翻转、锐化、亮度和对比度
- Open CV学习记录(三)——创建、采集新图像
- Open CV学习记录(四)——Sfm、SIFT、压缩感知
- Open CV学习记录(五)——离群点、访问图像像素、remap、resize
- Open CV学习记录(六)——图像的翻转
- Open CV学习记录(九)——仿射变换
- Open CV学习记录(十五)—读取视频,处理后保存
- Open CV学习记录(十六)—从视频中取每一帧保存
- Open CV学习记录(十七)—从图上显示某点的坐标
- Open CV学习记录(二十)—Mat的运算和Rect
- POJ 3984---迷宫问题
- chromium for linux 编译
- Linux下搭建tomcat集群全记录
- notepad++运行python
- 模拟hibernate(反射+sql拼接)
- Open CV学习记录(十三)——HcVision码流
- 第十周项目三-利用二叉树遍历思想解决问题
- 分布式系统的特点及设计理念
- 带你去看——WRC 2016 世界机器人博览会
- UGUI 如何判断鼠标停在UI上
- 【leetcode】441. Arranging Coins【E】
- 右左法则----复杂指针解析
- 多维数组
- 定位:提高生产力的开端