海康设备获取YV12图像-不用rtsp

概要:

         海康威视是目前中国领先的监控产品供应商,在我们很多项目中需要使用到他的产品;所以接入他的流变得很有必要。本文记录了如何接入海康威视的SDK,并获私有码流,随后得到NV12序列。本文出自CSDN-固本培元。转载注明出处,交流邮箱:[email protected]

准备:

海康SDK的下载地址:我下载的win64的。根据你自己的需求下载吧。

http://www.hikvision.com/cn/download_more_570.html

这里笔者还推荐一个很有用的海康的客户端软件:

http://www.hikvision.com/cn/download_more_390.html

4200/4000在DVS配置以及DVS密码丢失后可以起到很大帮助作用。(笔者对DVS的开发是接手以前一个同事的工作,密码丢失了,如果你的密码也忘记了的话,可以这样获取,有的DVS拆开后也同样没有复位键,通过将设备的序列号给售后后,他给你一个超级密码,用这个超级密码通过这个客户端就可以重置密码了。)


sdk下载后有一个clientDemo可以直接运行。通过它就可以预览和检测DVS的运行状态了。细节不用说了,很简单。

然后就是他官网文档的一些标志调用过程和示例代码需要看看,逼着推荐看这个:

设备网络SDK编程指南(DVR).pdf

其中有一节:预览模块的示例代码 好好看看就可以很好完成本文叙述的主题。

注意事项:

如果仅仅有如下dll库,编译和运行时都不会报错,但是解码回调会直接没有反应,坑爹啊。所以必须加上其他的dll库

海康设备获取YV12图像-不用rtsp_第1张图片

加上所有的dll库后如下图所示了。所以以后不要自作聪明,直接减去个人觉得没有用的dll库了。。分析原因:回调的函数实体在运行时需要调用。不过,个人觉得正常情况下应报错才对啊。

海康设备获取YV12图像-不用rtsp_第2张图片



最后通过海康SDK获取到的IYUV位图数据通过yuvviewer看到的图像如下图所示:

海康设备获取YV12图像-不用rtsp_第3张图片



参考代码:


注: 在使用下面代码时,配置项部分,需要略微修改。

[plain]  view plain copy
  1. #include    
  2. #include "Windows.h"   
  3. #include   
  4. #include   
  5. #include "HCNetSDK.h"   
  6. #include "plaympeg4.h"   
  7. #include    
  8.   
  9. #include   
  10. #include   
  11.   
  12. #include   
  13.   
  14. using namespace std;   
  15.   
  16.   
  17. typedef HWND (WINAPI *PROCGETCONSOLEWINDOW)();   
  18. PROCGETCONSOLEWINDOW ConsoleWindow;   
  19.   
  20. LONG lPort=-1; //全局的播放库port号   
  21. HWND hWnd ;  
  22.   
  23.   
  24.   
  25. static char HK_Addr[100]  ;  
  26. static int  HK_Port  ;  
  27. static char HK_USR[100]  ;  
  28. static char HK_PASSWORD[100]  ;  
  29. static int  HK_PreViewChannel ;  
  30.   
  31.   
  32. void Fprintf_Binary(const char * Path,char* buf,int Len,const char* Mode)    
  33. {    
  34.     FILE * pFile;    
  35.     // Mode binary "wb" binary append "ab+"  
  36.     pFile = fopen (Path, Mode);    
  37.   
  38.     fwrite (buf , sizeof(char), Len, pFile);    
  39.   
  40.     fclose (pFile);    
  41. }   
  42. //  
  43. 解码回调  
  44. void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)  
  45. {  
  46.     //printf("            @@@@Calling DecCBFun!\n");  
  47.     long lFrameType = pFrameInfo->nType;  
  48.     if (lFrameType ==T_AUDIO16)  
  49.     {  
  50.         //printf("Audio nStamp:%d\n",pFrameInfo->nStamp);  
  51.     }  
  52.     else if(lFrameType ==T_YV12)  
  53.     {     
  54.         //printf("Video nStamp:%d\n",pFrameInfo->nStamp);  
  55.   
  56.         //Fprintf_Binary("HK.yuv",pBuf,nSize,"ab+");  
  57.         if(!CheckShmOccupy(SHM_OCCUPY_BY_HK)){  
  58.             memcpy(g_shm_addr[VIDEO_CHANNEL_0]+SHM_OFFSET,pBuf,nSize);  
  59.             SetSHM_Ready(g_shm_addr[VIDEO_CHANNEL_0],SHM_IMG_READY_BIT,SHM_IMG_STATUS_READY);  
  60.         }  
  61.     }  
  62.     else  
  63.     {  
  64.   
  65.     }  
  66. }  
  67.   
  68. void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,void* dwUser)   
  69. {   
  70.     hWnd = GetConsoleWindow();   
  71.     static int count =0 ;  
  72.   
  73.     //printf("RealDataCallBack %d !\n",count++);  
  74.   
  75.     switch (dwDataType)   
  76.     {   
  77.     case NET_DVR_SYSHEAD: //系统头   
  78.         printf("                        NET_DVR_SYSHEAD\n");  
  79.         if (!PlayM4_GetPort(&lPort)) //获取播放库未使用的通道号   
  80.         {   
  81.             break;   
  82.         }   
  83.         //m_iPort = lPort;   
  84.         //第一次回调的是系统头,将获取的播放库port号赋值给全局port,下次回调数据时即使用此port号播放   
  85.         if (dwBufSize > 0)   
  86.         {   
  87.             if (!PlayM4_SetStreamOpenMode(lPort, STREAME_REALTIME)) //设置实时流播放模式   
  88.             {   
  89.                 printf("PlayM4_SetStreamOpenMode Error\n");  
  90.                 break;   
  91.             }   
  92.             if (!PlayM4_OpenStream(lPort, pBuffer, dwBufSize, 1024*1024)) //打开流接口   
  93.             {   
  94.                 printf("PlayM4_OpenStream Error\n");  
  95.                 break;   
  96.             }   
  97.             //  
  98.             ///设置解码回调函数  
  99.             if (!PlayM4_SetDecCallBackMend(lPort,DecCBFun,(long)dwUser))  
  100.             //if (!PlayM4_SetDecCallBack(lPort,DecCBFun))  
  101.             {  
  102.                 printf("Decode CallBack Set Error!\n");  
  103.                 PlayM4_GetLastError(lPort);  
  104.                 break;  
  105.             }  
  106.             else{  
  107.                 printf("DecCallBack Set OK!!!\n");  
  108.             }  
  109.             if (!PlayM4_Play(lPort, hWnd)) //播放开始   
  110.             {   
  111.                 printf("PlayM4_Play Error\n");  
  112.                 break;   
  113.             }   
  114.         }   
  115.         break;   
  116.     case NET_DVR_STREAMDATA: //码流数据   
  117.         //printf("    NET_DVR_STREAMDATA\n");  
  118.         if (dwBufSize > 0 && lPort != -1)   
  119.         {   
  120.             if (!PlayM4_InputData(lPort, pBuffer, dwBufSize))   
  121.             {   
  122.                 break;   
  123.             }   
  124.         }   
  125.         break;   
  126.     default: //其他数据   
  127.         printf("        OTHERS\n");  
  128.         if (dwBufSize > 0 && lPort != -1)   
  129.         {   
  130.             if (!PlayM4_InputData(lPort, pBuffer, dwBufSize))   
  131.             {   
  132.                 break;   
  133.             }   
  134.         }   
  135.         break;   
  136.     }   
  137. }   
  138. void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)   
  139. {   
  140.     char tempbuf[256] = {0};   
  141.     switch(dwType)   
  142.     {   
  143.     case EXCEPTION_RECONNECT: //预览时重连   
  144.         printf("----------reconnect--------%d\n", time(NULL));   
  145.         break;   
  146.     default:   
  147.         break;   
  148.     }   
  149. }   
  150. void LoadConfiguration()  
  151. {  
  152.     char ConfigVal[100] ;  
  153.   
  154.     // HK Width  and Height   
  155.     if(GetConfigVal("CenDVCGenConfig.ini","HK_WIDTH",ConfigVal,"GettingHKWidth","GettingHKWidthError!!!\n")){  
  156.         HK_RAW_VIDEO_WIDTH = atoi(ConfigVal);  
  157.     }else{  
  158.         printf("Loading HK Configuration Width Error!!!\n");  
  159.         exit(-1);  
  160.     }  
  161.     if(GetConfigVal("CenDVCGenConfig.ini","HK_HEIGHT",ConfigVal,"GettingHKHeight","GettingHKHeightError!!!\n")){  
  162.         HK_RAW_VIDEO_HEIGHT = atoi(ConfigVal);  
  163.     }else{  
  164.         printf("Loading HK Configuration Height Error!!!\n");  
  165.         exit(-1);  
  166.     }  
  167.   
  168.     // Addr and Port  
  169.     if(GetConfigVal("CenDVCGenConfig.ini","HK_Addr",ConfigVal,"GettingHK_Addr","GettingHK_AddrError!!!\n")){  
  170.         strcpy(HK_Addr,ConfigVal);  
  171.     }else{  
  172.         printf("Loading HK Configuration HK_Addr Error!!!\n");  
  173.         exit(-1);  
  174.     }  
  175.     if(GetConfigVal("CenDVCGenConfig.ini","HK_Port",ConfigVal,"GettingHK_Port","GettingHK_PortError!!!\n")){  
  176.         HK_Port = atoi(ConfigVal);  
  177.     }else{  
  178.         printf("Loading HK Configuration HK_Port Error!!!\n");  
  179.         exit(-1);  
  180.     }  
  181.   
  182.     //USR  and Password   
  183.     if(GetConfigVal("CenDVCGenConfig.ini","HK_USR",ConfigVal,"GettingHK_USR","GettingHK_USRError!!!\n")){  
  184.         strcpy(HK_USR,ConfigVal);  
  185.     }else{  
  186.         printf("Loading HK Configuration HK_USR Error!!!\n");  
  187.         exit(-1);  
  188.     }  
  189.     if(GetConfigVal("CenDVCGenConfig.ini","HK_PASSWORD",ConfigVal,"GettingHK_PASSWORD","GettingHK_PASSWORDError!!!\n")){  
  190.         strcpy(HK_PASSWORD,ConfigVal);  
  191.     }else{  
  192.         printf("Loading HK Configuration HK_PASSWORD Error!!!\n");  
  193.         exit(-1);  
  194.     }  
  195.   
  196.     //PreviewChannel  
  197.     if(GetConfigVal("CenDVCGenConfig.ini","HK_PreViewChannel",ConfigVal,"GettingHK_PreViewChannel","GettingHK_PreViewChannelError!!!\n")){  
  198.         HK_PreViewChannel = atoi(ConfigVal);  
  199.     }else{  
  200.         printf("Loading HK Configuration HK_PreViewChannel Error!!!\n");  
  201.         exit(-1);  
  202.     }  
  203.   
  204.   
  205. }  
  206. void main() {   
  207.     // 初始化   
  208.   
  209.     LoadConfiguration();  
  210.     InitSys();  
  211.     NET_DVR_Init();   
  212.     //设置连接时间与重连时间   
  213.     NET_DVR_SetConnectTime(2000, 1);   
  214.     NET_DVR_SetReconnect(10000, true);   
  215.   
  216.     //---------------------------------------   
  217.     // 获取控制台窗口句柄   
  218.     //HMODULE hKernel32 = GetModuleHandle("kernel32");   
  219.     //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");   
  220.     HMODULE hKernel32 = GetModuleHandle("kernel32");   
  221.     ConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");   
  222.   
  223.   
  224.     //---------------------------------------   
  225.     // 注册设备   
  226.     LONG lUserID;   
  227.     NET_DVR_DEVICEINFO_V30 struDeviceInfo;   
  228.     //lUserID = NET_DVR_Login_V30("172.16.1.251", 8000, "admin", "12345", &struDeviceInfo);   
  229.     //lUserID = NET_DVR_Login_V30("192.168.4.237", 8000, "admin", "12345", &struDeviceInfo);   
  230.     lUserID = NET_DVR_Login_V30(HK_Addr,HK_Port, HK_USR,HK_PASSWORD, &struDeviceInfo);   
  231.     if (lUserID < 0)   
  232.     {   
  233.         printf("Login error, %d\n", NET_DVR_GetLastError());   
  234.         NET_DVR_Cleanup();   
  235.         return;   
  236.     }   
  237.     //---------------------------------------   
  238.     //设置异常消息回调函数   
  239.     NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);   
  240.     //---------------------------------------   
  241.     //启动预览并设置回调数据流   
  242.     LONG lRealPlayHandle;   
  243.     NET_DVR_PREVIEWINFO struPlayInfo = {0};   
  244.     struPlayInfo.hPlayWnd = hWnd; //需要SDK解码时句柄设为有效值,仅取流不解码时可设为空   
  245.     //struPlayInfo.hPlayWnd = 0; //需要SDK解码时句柄设为有效值,仅取流不解码时可设为空   
  246.     struPlayInfo.lChannel = HK_PreViewChannel; //预览通道号   
  247.     struPlayInfo.dwStreamType = 0; //0-主码流,1-子码流,2-码流3,3-码流4,以此类推   
  248.     struPlayInfo.dwLinkMode = 0; //0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP   
  249.     struPlayInfo.bBlocked = 0; //0- 非阻塞取流,1- 阻塞取流   
  250.   
  251.     unsigned long lpdwVideoStandard;  
  252.   
  253.     //bool ret = NET_DVR_MatrixGetVideoStandard(lUserID, struPlayInfo.lChannel,&lpdwVideoStandard );  
  254.     //DWORD error = NET_DVR_GetLastError();  
  255.   
  256.     lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, g_RealDataCallBack_V30, NULL);   
  257.       
  258.   
  259.   
  260.     if (lRealPlayHandle < 0)   
  261.     {   
  262.         printf("NET_DVR_RealPlay_V40 error\n");   
  263.         NET_DVR_Logout(lUserID);   
  264.         NET_DVR_Cleanup();   
  265.         return;   
  266.     }   
  267.     while(1)  
  268.         Sleep(10000);   
  269.   
  270.     //---------------------------------------   
  271.     //关闭预览   
  272.     NET_DVR_StopRealPlay(lRealPlayHandle);   
  273.     //注销用户   
  274.     NET_DVR_Logout(lUserID);   
  275.     NET_DVR_Cleanup();   
  276.     return;   
  277. }   







参考文章:http://blog.csdn.net/gubenpeiyuan/article/details/24346125

你可能感兴趣的:(流媒体)