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