海康威视IPCamera图像捕获 二种方法

来源:互联网 发布:centos 7 mirror 编辑:程序博客网 时间:2024/05/16 06:45

所使用海康威视摄像头型号:DS-2CD4026FWD-(A)(P)


海康威视IPCamera图像捕获方法有两种:

(1)利用SDK里面的NET_DVR_CaptureJPEGPicture_NEW进行视频抓图

(2)捕获实时流,将实时流解码成YV12,然后转换成RGB

海康威视IPCamera图像捕获


捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(一)

捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(二)


所使用海康威视摄像头型号:DS-2CD4026FWD-(A)(P)


海康威视IPCamera图像捕获方法有两种:

(1)利用SDK里面的NET_DVR_CaptureJPEGPicture_NEW进行视频抓图

(2)捕获实时流,将实时流解码成YV12,然后转换成RGB



在这篇博文里,我先介绍第一种方法。

第一种方法,关键是调用NET_DVR_CaptureJPEGPicture_NEW这个函数。关于这个函数的参数,可以在SDK中找到,我这里截个图以作说明。


这个函数Ret是用于返回该图像大小的一个参数,但是该函数的这个参数大概是没有用引用或者指针的方式来传递参数,导致返回值一直是我初始化的0,因此为后面的操作带来了些许的不便——不得不使用一个较大的内存来保存图像一定能存储的下。

NET_DVR_CaptureJPEGPicture_NEW这个函数是将单帧数据捕获并保存成JPEG,存放在指定的内存空间中。也就是内存里的JPEG。为了获得OpenCV能处理的IplImage图像,必须在内存中进行解码。

OpenCV在内存中解码的函数只有一个:imdecode,下图是imdecode的说明


该函数要求buf必须是数组或者是byte类型的vector. 因此需要对char * 类型的JPEG压缩图像进行存储格式转换。


[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #include <cstdio>  
  2. #include <iostream>  
  3. #include <ctime>  
  4. #include <Windows.h>  
  5. #include "HCNetSDK.h"  
  6. #include "highgui.h"  
  7. #include "cv.h"  
  8.   
  9.   
  10. using namespace cv;  
  11. using namespace std;  
  12.   
  13.   
  14. //typedef HWND (WINAPI *PROCGETCONSOLEWINDOW)();  
  15. //PROCGETCONSOLEWINDOW GetConsoleWindow;  
  16.   
  17. int main(int argc, char * argv[])   
  18. {     
  19.     //---------------------------------------  
  20.     // 初始化  
  21.     NET_DVR_Init();  
  22.     //设置连接时间与重连时间  
  23.     NET_DVR_SetConnectTime(2000, 1);  
  24.     NET_DVR_SetReconnect(10000, true);  
  25.       
  26.     //---------------------------------------  
  27.     //获取控制台窗口句柄  
  28.     //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32");  
  29.     //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");  
  30.   
  31.       
  32.     //---------------------------------------  
  33.     // 注册设备  
  34.     LONG lUserID;  
  35.     NET_DVR_DEVICEINFO_V30 struDeviceInfo;  
  36.     lUserID = NET_DVR_Login_V30("10.102.7.88", 8000, "admin""12345", &struDeviceInfo);  
  37.     if (lUserID < 0)  
  38.     {  
  39.         printf("Login error, %d\n", NET_DVR_GetLastError());  
  40.         NET_DVR_Cleanup();  
  41.         return -1;  
  42.     }     
  43.   
  44.       
  45.     //---------------------------------------  
  46.     //cvNamedWindow("camera",CV_WINDOW_AUTOSIZE);  
  47.     IplImage* frame;  
  48.     //定义JPEG图像质量  
  49.     LPNET_DVR_JPEGPARA JpegPara = new NET_DVR_JPEGPARA;  
  50.     JpegPara->wPicQuality = 0;  
  51.     JpegPara->wPicSize = 9;  
  52.       
  53.     char * Jpeg = new char[200*1024];  
  54.     DWORD len = 200*1024;  
  55.     LPDWORD Ret = 0;  
  56.               
  57.     if(!NET_DVR_SetCapturePictureMode(BMP_MODE))  
  58.     {  
  59.         cout<<"Set Capture Picture Mode error!"<<endl;  
  60.         cout<<"The error code is "<<NET_DVR_GetLastError()<<endl;  
  61.     }  
  62.   
  63.     //bool capture = NET_DVR_CaptureJPEGPicture(lUserID,1,JpegPara,"1111");  
  64.     vector<char>data(200*1024);  
  65.     while(1)  
  66.     {  
  67.     bool capture = NET_DVR_CaptureJPEGPicture_NEW(lUserID,1,JpegPara,Jpeg,len,Ret);  
  68.     if(!capture)  
  69.     {  
  70.         printf("Error: NET_DVR_CaptureJPEGPicture_NEW = %d", NET_DVR_GetLastError());  
  71.         return -1;    
  72.     }     
  73.   
  74.     for(int i=0;i<200*1024;i++)  
  75.         data[i] = Jpeg[i];  
  76.   
  77.     Mat img = imdecode(Mat(data),1);  
  78.     imshow("camera",img);  
  79.     waitKey(1);  
  80.       
  81.     }  
  82.   
  83.     //FILE * fp = fopen("3.jpg","wb");  
  84.     //fwrite(Jpeg,1,123*1024,fp);  
  85.     //fclose(fp);  
  86.       
  87.     return 0;  
  88. }  

运行这个代码当然OpenCV的配置不能少,HCNetSDK.h也必须包含进工程。

运行这个程序,可以捕获到图像,但是我计算了下时间,在调用 NET_DVR_CaptureJPEGPicture_NEW(lUserID,1,JpegPara,Jpeg,len,Ret);这一句话的时候,用时300ms,这个耗时太长,无法实时!但是如果对实时无要求,用这个也可以了,好理解!




/********************************************************************************************************************************************************************************

第二部分博文内容

********************************************************************************************************************************************************************************、


在上一篇博文里,我介绍了第一种方法,但是由于NET_DVR_CaptureJPEGPicture_NEW该函数执行需要较长时间,无法实时,所以必须继续第二种方法。

在这篇博文里,我将介绍第二种方法,将捕获到的海康威视IPCamera摄像头图像转成OpenCV能处理的IplImage图像。


在实现完捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(一)里面的方法后,发现不能实时,这个系统我是要做给给人看的,是需要实时演示的,这样子肯定是不行的。纠结了好久!然后查看海康威视《设备网络SDK使用手册_V4.2》,里面有一个预览模块示例程序,可惜我一直运行不了,报出的错误是PROCGETCONSOLEWINDOW GetConsoleWindow中的GetConsoleWindow被重定义,后来一直调试没调成功。


实在是没辙了,打海康客服,不过海康的客服我实在无语,北京的完全无法接通,直接打杭州的,打了四五遍终于有个人接电话了,对方不懂,然后说让个工程师回电话。OK,终于回了。他告诉我http://www.hikvision.com/cn/download_more_401.html 这里是有例程的,有分功能示例!突然间有了希望了,例程是VC6.0工程,改了一些地方后,终于能运行了。于是,将他的MFC工程相关的代码抠出来,重组。于是实现了捕获YV12格式的视频流的功能,光有YV12还是不行的,需要将YV12转成YUV4:4:4的,然后再将YUV色度空间转换成RGB色度空间,这个过程是在信件的DecBFun回调函数(回调函数请看这里!)里面执行的。


不多说了,上代码!


[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <iostream>  
  4. #include "Windows.h"  
  5. #include "HCNetSDK.h"  
  6. #include "PlayM4.h"  
  7. #include <opencv2\opencv.hpp>  
  8. #include "cv.h"  
  9. #include "highgui.h"  
  10. #include <time.h>  
  11. #define USECOLOR 1  
  12. using namespace std;  
  13. using namespace std;  
  14.   
  15. //--------------------------------------------  
  16. int iPicNum=0;//Set channel NO.  
  17. LONG nPort=-1;  
  18. HWND hWnd=NULL;  
  19.   
  20.   
  21. void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)  
  22. {  
  23.    int col,row;  
  24.    unsigned int Y,U,V;  
  25.    int tmp;  
  26.    int idx;  
  27.   
  28.   //printf("widthStep=%d.\n",widthStep);  
  29.   
  30.    for (row=0; row<height; row++)  
  31.    {  
  32.       idx=row * widthStep;  
  33.       int rowptr=row*width;  
  34.   
  35.       for (col=0; col<width; col++)  
  36.       {  
  37.          //int colhalf=col>>1;  
  38.          tmp = (row/2)*(width/2)+(col/2);  
  39. //         if((row==1)&&( col>=1400 &&col<=1600))  
  40. //         {   
  41. //          printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
  42. //          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);  
  43. //         }   
  44.          Y=(unsigned int) inYv12[row*width+col];  
  45.          U=(unsigned int) inYv12[width*height+width*height/4+tmp];  
  46.          V=(unsigned int) inYv12[width*height+tmp];  
  47. //         if ((col==200))  
  48. //         {   
  49. //         printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
  50. //         printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp);  
  51. //         return ;  
  52. //         }  
  53.          if((idx+col*3+2)> (1200 * widthStep))  
  54.          {  
  55.           //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2);  
  56.          }   
  57.          outYuv[idx+col*3]   = Y;  
  58.          outYuv[idx+col*3+1] = U;  
  59.          outYuv[idx+col*3+2] = V;  
  60.       }  
  61.    }  
  62.    //printf("col=%d,row=%d.\n",col,row);  
  63. }  
  64.   
  65.   
  66.   
  67. //解码回调 视频为YUV数据(YV12),音频为PCM数据  
  68. void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)  
  69. {  
  70.     long lFrameType = pFrameInfo->nType;   
  71.   
  72.     if(lFrameType ==T_YV12)  
  73.     {  
  74. #if USECOLOR  
  75.     //int start = clock();  
  76.     IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量    
  77.     yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像  
  78.     IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);    
  79.     cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB);    
  80.     //int end = clock();  
  81. #else  
  82.     IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1);    
  83.     memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight);   
  84. #endif  
  85.     //printf("%d\n",end-start);  
  86.     cvShowImage("IPCamera",pImg);  
  87.     cvWaitKey(1);  
  88. #if USECOLOR  
  89.     cvReleaseImage(&pImgYCrCb);  
  90.     cvReleaseImage(&pImg);  
  91. #else  
  92.     cvReleaseImage(&pImg);  
  93. #endif  
  94.     //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile);  
  95.     //fwrite(pBuf,nSize,1,fp);  
  96.     }  
  97.     /*************** 
  98.     else if (lFrameType ==T_AUDIO16) 
  99.     { 
  100.         //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); 
  101.          
  102.     } 
  103.     else 
  104.     { 
  105.  
  106.     } 
  107.     *******************/  
  108.   
  109. }  
  110.   
  111.   
  112. ///实时流回调  
  113. void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser)  
  114. {  
  115.     DWORD dRet;  
  116.     switch (dwDataType)  
  117.     {  
  118.     case NET_DVR_SYSHEAD:    //系统头  
  119.         if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号  
  120.         {  
  121.             break;  
  122.         }  
  123.         if(dwBufSize > 0)  
  124.         {  
  125.             if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024))  
  126.             {  
  127.                 dRet=PlayM4_GetLastError(nPort);  
  128.                 break;  
  129.             }  
  130.             //设置解码回调函数 只解码不显示  
  131.             if (!PlayM4_SetDecCallBack(nPort,DecCBFun))  
  132.             {  
  133.                 dRet=PlayM4_GetLastError(nPort);  
  134.                 break;  
  135.             }  
  136.           
  137.             //设置解码回调函数 解码且显示  
  138.             //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))  
  139.             //{  
  140.             //  dRet=PlayM4_GetLastError(nPort);  
  141.             //  break;  
  142.             //}  
  143.   
  144.             //打开视频解码  
  145.             if (!PlayM4_Play(nPort,hWnd))  
  146.             {  
  147.                 dRet=PlayM4_GetLastError(nPort);  
  148.                 break;  
  149.             }  
  150.   
  151.             //打开音频解码, 需要码流是复合流  
  152.             if (!PlayM4_PlaySound(nPort))  
  153.             {  
  154.                 dRet=PlayM4_GetLastError(nPort);  
  155.                 break;  
  156.             }         
  157.         }  
  158.         break;  
  159.           
  160.     case NET_DVR_STREAMDATA:   //码流数据  
  161.         if (dwBufSize > 0 && nPort != -1)  
  162.         {  
  163.             BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);  
  164.             while (!inData)  
  165.             {  
  166.                 Sleep(10);  
  167.                 inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);  
  168.                 OutputDebugString(L"PlayM4_InputData failed \n");     
  169.             }  
  170.         }  
  171.         break;    
  172.     }         
  173. }  
  174.   
  175. void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)  
  176. {  
  177.     char tempbuf[256] = {0};  
  178.     switch(dwType)   
  179.     {  
  180.     case EXCEPTION_RECONNECT:    //预览时重连  
  181.     printf("----------reconnect--------%d\n", time(NULL));  
  182.     break;  
  183.     default:  
  184.     break;  
  185.     }  
  186. }  
  187.   
  188. void main() {  
  189.   
  190.   //---------------------------------------  
  191.   // 初始化  
  192.   NET_DVR_Init();  
  193.   //设置连接时间与重连时间  
  194.   NET_DVR_SetConnectTime(2000, 1);  
  195.   NET_DVR_SetReconnect(10000, true);  
  196.     
  197.   //---------------------------------------  
  198.   // 获取控制台窗口句柄  
  199.   //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32");  
  200.   //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");  
  201.   
  202.   //---------------------------------------  
  203.   // 注册设备  
  204.   LONG lUserID;  
  205.   NET_DVR_DEVICEINFO_V30 struDeviceInfo;  
  206.   lUserID = NET_DVR_Login_V30("10.102.7.88", 8000, "admin""12345", &struDeviceInfo);  
  207.   if (lUserID < 0)  
  208.   {  
  209.        printf("Login error, %d\n", NET_DVR_GetLastError());  
  210.        NET_DVR_Cleanup();  
  211.        return;  
  212.   }  
  213.   
  214.   //---------------------------------------  
  215.   //设置异常消息回调函数  
  216.   NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);  
  217.   
  218.   
  219.   //cvNamedWindow("IPCamera");  
  220.   //---------------------------------------  
  221.   //启动预览并设置回调数据流   
  222.   NET_DVR_CLIENTINFO ClientInfo;  
  223.   ClientInfo.lChannel = 1;        //Channel number 设备通道号  
  224.   ClientInfo.hPlayWnd = NULL;     //窗口为空,设备SDK不解码只取流  
  225.   ClientInfo.lLinkMode = 0;       //Main Stream  
  226.   ClientInfo.sMultiCastIP = NULL;  
  227.     
  228.   LONG lRealPlayHandle;  
  229.   lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE);  
  230.   if (lRealPlayHandle<0)  
  231.   {  
  232.     printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n",NET_DVR_GetLastError());  
  233.     return;  
  234.   }  
  235.   
  236.   //cvWaitKey(0);  
  237.   Sleep(-1);  
  238.   
  239.   //fclose(fp);  
  240.   //---------------------------------------  
  241.   //关闭预览  
  242.   if(!NET_DVR_StopRealPlay(lRealPlayHandle))  
  243.   {  
  244.     printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError());  
  245.     return;  
  246.   }  
  247.   //注销用户  
  248.   NET_DVR_Logout(lUserID);  
  249.   NET_DVR_Cleanup();  
  250.   
  251.   return;  
  252. }  


终于能够实时捕获图像了,而且转换成了OpenCV能够处理的图像格式。

在这个过程中搜了很多资料,但是没有一个地方能详细说明,不过最终还是把这个给解决了。

 

附加说明:如果最后要做图像处理而不是像我这样只是将采集的图像显示出来,那么下面的语句是不需要的。

  1. #if USECOLOR  
  2.     cvReleaseImage(&pImgYCrCb);  
  3.     cvReleaseImage(&pImg);  
  4. #else  
  5.     cvReleaseImage(&pImg);  
  6. #endif  

 

 后记:虽然这个功能实现了,但是与我的图像处理函数如何结合到一起?我想到的是用链队列,双线程。链队列代码请看这里!

 


写这两篇博文的目的其实也是想让处于探索过程中的开发人员能少走些弯路,节省些时间,衷心希望本文能够帮到你!


因为本人已经毕业,项目也早就已经结题了,手头上不再具有可供调试的硬件设备,因此对于大家所碰到的问题,我基本上也已经无法回答了,非常抱歉!如果大家在开发海康威视摄像头的过程中遇到了什么问题可以去跟海康客服去沟通,如果您所在地区的客服无法联系上的话,请直接联系杭州总部的客服。

最后,对之前很长一段时间对大家所提出的问题一直置之不理再次表示道歉!谢谢大家的支持!


**************************************************************************************

转载请注明出处:http://blog.csdn.net/wanghuiqi2008/article/details/31410509

**************************************************************************************




在上一篇博文里,我介绍了第一种方法,但是由于NET_DVR_CaptureJPEGPicture_NEW该函数执行需要较长时间,无法实时,所以必须继续第二种方法。

在这篇博文里,我将介绍第二种方法,将捕获到的海康威视IPCamera摄像头图像转成OpenCV能处理的IplImage图像。


在实现完捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(一)里面的方法后,发现不能实时,这个系统我是要做给给人看的,是需要实时演示的,这样子肯定是不行的。纠结了好久!然后查看海康威视《设备网络SDK使用手册_V4.2》,里面有一个预览模块示例程序,可惜我一直运行不了,报出的错误是PROCGETCONSOLEWINDOW GetConsoleWindow中的GetConsoleWindow被重定义,后来一直调试没调成功。


实在是没辙了,打海康客服,不过海康的客服我实在无语,北京的完全无法接通,直接打杭州的,打了四五遍终于有个人接电话了,对方不懂,然后说让个工程师回电话。OK,终于回了。他告诉我http://www.hikvision.com/cn/download_more_401.html 这里是有例程的,有分功能示例!突然间有了希望了,例程是VC6.0工程,改了一些地方后,终于能运行了。于是,将他的MFC工程相关的代码抠出来,重组。于是实现了捕获YV12格式的视频流的功能,光有YV12还是不行的,需要将YV12转成YUV4:4:4的,然后再将YUV色度空间转换成RGB色度空间,这个过程是在信件的DecBFun回调函数(回调函数请看这里!)里面执行的。


不多说了,上代码!


[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <iostream>  
  4. #include "Windows.h"  
  5. #include "HCNetSDK.h"  
  6. #include "PlayM4.h"  
  7. #include <opencv2\opencv.hpp>  
  8. #include "cv.h"  
  9. #include "highgui.h"  
  10. #include <time.h>  
  11. #define USECOLOR 1  
  12. using namespace std;  
  13. using namespace std;  
  14.   
  15. //--------------------------------------------  
  16. int iPicNum=0;//Set channel NO.  
  17. LONG nPort=-1;  
  18. HWND hWnd=NULL;  
  19.   
  20.   
  21. void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)  
  22. {  
  23.    int col,row;  
  24.    unsigned int Y,U,V;  
  25.    int tmp;  
  26.    int idx;  
  27.   
  28.   //printf("widthStep=%d.\n",widthStep);  
  29.   
  30.    for (row=0; row<height; row++)  
  31.    {  
  32.       idx=row * widthStep;  
  33.       int rowptr=row*width;  
  34.   
  35.       for (col=0; col<width; col++)  
  36.       {  
  37.          //int colhalf=col>>1;  
  38.          tmp = (row/2)*(width/2)+(col/2);  
  39. //         if((row==1)&&( col>=1400 &&col<=1600))  
  40. //         {   
  41. //          printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
  42. //          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);  
  43. //         }   
  44.          Y=(unsigned int) inYv12[row*width+col];  
  45.          U=(unsigned int) inYv12[width*height+width*height/4+tmp];  
  46.          V=(unsigned int) inYv12[width*height+tmp];  
  47. //         if ((col==200))  
  48. //         {   
  49. //         printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
  50. //         printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp);  
  51. //         return ;  
  52. //         }  
  53.          if((idx+col*3+2)> (1200 * widthStep))  
  54.          {  
  55.           //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2);  
  56.          }   
  57.          outYuv[idx+col*3]   = Y;  
  58.          outYuv[idx+col*3+1] = U;  
  59.          outYuv[idx+col*3+2] = V;  
  60.       }  
  61.    }  
  62.    //printf("col=%d,row=%d.\n",col,row);  
  63. }  
  64.   
  65.   
  66.   
  67. //解码回调 视频为YUV数据(YV12),音频为PCM数据  
  68. void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)  
  69. {  
  70.     long lFrameType = pFrameInfo->nType;   
  71.   
  72.     if(lFrameType ==T_YV12)  
  73.     {  
  74. #if USECOLOR  
  75.     //int start = clock();  
  76.     IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量    
  77.     yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像  
  78.     IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);    
  79.     cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB);    
  80.     //int end = clock();  
  81. #else  
  82.     IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1);    
  83.     memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight);   
  84. #endif  
  85.     //printf("%d\n",end-start);  
  86.     cvShowImage("IPCamera",pImg);  
  87.     cvWaitKey(1);  
  88. #if USECOLOR  
  89.     cvReleaseImage(&pImgYCrCb);  
  90.     cvReleaseImage(&pImg);  
  91. #else  
  92.     cvReleaseImage(&pImg);  
  93. #endif  
  94.     //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile);  
  95.     //fwrite(pBuf,nSize,1,fp);  
  96.     }  
  97.     /*************** 
  98.     else if (lFrameType ==T_AUDIO16) 
  99.     { 
  100.         //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); 
  101.          
  102.     } 
  103.     else 
  104.     { 
  105.  
  106.     } 
  107.     *******************/  
  108.   
  109. }  
  110.   
  111.   
  112. ///实时流回调  
  113. void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser)  
  114. {  
  115.     DWORD dRet;  
  116.     switch (dwDataType)  
  117.     {  
  118.     case NET_DVR_SYSHEAD:    //系统头  
  119.         if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号  
  120.         {  
  121.             break;  
  122.         }  
  123.         if(dwBufSize > 0)  
  124.         {  
  125.             if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024))  
  126.             {  
  127.                 dRet=PlayM4_GetLastError(nPort);  
  128.                 break;  
  129.             }  
  130.             //设置解码回调函数 只解码不显示  
  131.             if (!PlayM4_SetDecCallBack(nPort,DecCBFun))  
  132.             {  
  133.                 dRet=PlayM4_GetLastError(nPort);  
  134.                 break;  
  135.             }  
  136.           
  137.             //设置解码回调函数 解码且显示  
  138.             //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))  
  139.             //{  
  140.             //  dRet=PlayM4_GetLastError(nPort);  
  141.             //  break;  
  142.             //}  
  143.   
  144.             //打开视频解码  
  145.             if (!PlayM4_Play(nPort,hWnd))  
  146.             {  
  147.                 dRet=PlayM4_GetLastError(nPort);  
  148.                 break;  
  149.             }  
  150.   
  151.             //打开音频解码, 需要码流是复合流  
  152.             if (!PlayM4_PlaySound(nPort))  
  153.             {  
  154.                 dRet=PlayM4_GetLastError(nPort);  
  155.                 break;  
  156.             }         
  157.         }  
  158.         break;  
  159.           
  160.     case NET_DVR_STREAMDATA:   //码流数据  
  161.         if (dwBufSize > 0 && nPort != -1)  
  162.         {  
  163.             BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);  
  164.             while (!inData)  
  165.             {  
  166.                 Sleep(10);  
  167.                 inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);  
  168.                 OutputDebugString(L"PlayM4_InputData failed \n");     
  169.             }  
  170.         }  
  171.         break;    
  172.     }         
  173. }  
  174.   
  175. void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)  
  176. {  
  177.     char tempbuf[256] = {0};  
  178.     switch(dwType)   
  179.     {  
  180.     case EXCEPTION_RECONNECT:    //预览时重连  
  181.     printf("----------reconnect--------%d\n", time(NULL));  
  182.     break;  
  183.     default:  
  184.     break;  
  185.     }  
  186. }  
  187.   
  188. void main() {  
  189.   
  190.   //---------------------------------------  
  191.   // 初始化  
  192.   NET_DVR_Init();  
  193.   //设置连接时间与重连时间  
  194.   NET_DVR_SetConnectTime(2000, 1);  
  195.   NET_DVR_SetReconnect(10000, true);  
  196.     
  197.   //---------------------------------------  
  198.   // 获取控制台窗口句柄  
  199.   //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32");  
  200.   //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");  
  201.   
  202.   //---------------------------------------  
  203.   // 注册设备  
  204.   LONG lUserID;  
  205.   NET_DVR_DEVICEINFO_V30 struDeviceInfo;  
  206.   lUserID = NET_DVR_Login_V30("10.102.7.88", 8000, "admin""12345", &struDeviceInfo);  
  207.   if (lUserID < 0)  
  208.   {  
  209.        printf("Login error, %d\n", NET_DVR_GetLastError());  
  210.        NET_DVR_Cleanup();  
  211.        return;  
  212.   }  
  213.   
  214.   //---------------------------------------  
  215.   //设置异常消息回调函数  
  216.   NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);  
  217.   
  218.   
  219.   //cvNamedWindow("IPCamera");  
  220.   //---------------------------------------  
  221.   //启动预览并设置回调数据流   
  222.   NET_DVR_CLIENTINFO ClientInfo;  
  223.   ClientInfo.lChannel = 1;        //Channel number 设备通道号  
  224.   ClientInfo.hPlayWnd = NULL;     //窗口为空,设备SDK不解码只取流  
  225.   ClientInfo.lLinkMode = 0;       //Main Stream  
  226.   ClientInfo.sMultiCastIP = NULL;  
  227.     
  228.   LONG lRealPlayHandle;  
  229.   lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE);  
  230.   if (lRealPlayHandle<0)  
  231.   {  
  232.     printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n",NET_DVR_GetLastError());  
  233.     return;  
  234.   }  
  235.   
  236.   //cvWaitKey(0);  
  237.   Sleep(-1);  
  238.   
  239.   //fclose(fp);  
  240.   //---------------------------------------  
  241.   //关闭预览  
  242.   if(!NET_DVR_StopRealPlay(lRealPlayHandle))  
  243.   {  
  244.     printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError());  
  245.     return;  
  246.   }  
  247.   //注销用户  
  248.   NET_DVR_Logout(lUserID);  
  249.   NET_DVR_Cleanup();  
  250.   
  251.   return;  
  252. }  


终于能够实时捕获图像了,而且转换成了OpenCV能够处理的图像格式。

在这个过程中搜了很多资料,但是没有一个地方能详细说明,不过最终还是把这个给解决了。

 

附加说明:如果最后要做图像处理而不是像我这样只是将采集的图像显示出来,那么下面的语句是不需要的。

  1. #if USECOLOR  
  2.     cvReleaseImage(&pImgYCrCb);  
  3.     cvReleaseImage(&pImg);  
  4. #else  
  5.     cvReleaseImage(&pImg);  
  6. #endif  

 

 后记:虽然这个功能实现了,但是与我的图像处理函数如何结合到一起?我想到的是用链队列,双线程。链队列代码请看这里!

 


写这两篇博文的目的其实也是想让处于探索过程中的开发人员能少走些弯路,节省些时间,衷心希望本文能够帮到你!




转载请注明出处:http://blog.csdn.net/wanghuiqi2008/article/details/31410509



0 0
原创粉丝点击