环境:Red Hat Enterprise linux As5
SDK版本: CH-HCNetSDK(Linux)4.0.2.7
OpenCv:2.2.0
将控制台演示代码的 GetStream.cpp 覆盖为以下,就能转换成 IplImage 内存数据,IplImage *img 是YUV格式,IplImage *imgBgr 是BGR格式:
/*
* Copyright(C) 2010,Hikvision Digital Technology Co., Ltd
*
* File name:GetStream.cpp
* Discription:
* Version :1.0
* Author :panyd
* Create Date:2010_3_25
* Modification History:
*/
#ifdef _WIN32
#include <windows.h>
#elif defined(__linux__)
#include <unistd.h>
#endif
#include "HCNetSDK.h"
#include "public.h"
#include <stdio.h>
#include <time.h>
#include "playsdkpu.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
int lPort;
void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)
{
int col,row;
unsigned int Y,U,V;
int tmp;
int idx;
// unsigned int red,blue,green;
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);
}
void CALLBACK g_DecCBFun(int nPort,char * pBuf,int nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)
{
printf("call g_DecCBFun suceess.\n");
printf("nPort=%d,nSize=%d,pFrameInfo.nWidth=%ld,pFrameInfo.nHeight=%ld,\
pFrameInfo.nStamp=%ld,pFrameInfo.nType=%ld,pFrameInfo.nFrameRate=%ld.\n",
nPort,nSize,pFrameInfo->nWidth,pFrameInfo->nHeight,
pFrameInfo->nStamp,pFrameInfo->nType,pFrameInfo->nFrameRate);
switch (pFrameInfo->nType)
{
case T_AUDIO16: //音频数据
printf("pFrameInfo.nType is T_AUDIO16.\n");
break;
case T_RGB32: //系统头
printf("pFrameInfo.nType is T_RGB32.\n");
break;
case T_UYVY: //系统头
printf("pFrameInfo.nType is T_UYVY.\n");
break;
case T_YV12: //系统头
printf("pFrameInfo.nType is T_YV12.\n");
break;
default :
printf("Error pFrameInfo.nType.\n");
break;
}
IplImage *img = cvCreateImage(cvSize(1600, 1200), IPL_DEPTH_8U, 3);
printf("img->imageSize=%d.\n",img->imageSize);
printf("cvCreateImage sucess.\n");
CvScalar scal;
scal = cvGet2D(img,1199,1599);//获取像素点
double valY = scal.val[0];
double valU = scal.val[1];
double valV = scal.val[2];
printf("valY=%e, valU=%e,valV=%e.\n",valY,valU,valV);
yv12toYUV(img->imageData, pBuf, 1600, 1200,img->widthStep);
printf("yv12toYUV sucess.\n");
scal = cvGet2D(img,1199,1599);//获取像素点
valY = scal.val[0];
valU = scal.val[1];
valV = scal.val[2];
printf("valY=%e, valU=%e,valV=%e.\n",valY,valU,valV);
IplImage *imgBgr = cvCreateImage(cvSize(1600, 1200), IPL_DEPTH_8U, 3);
printf("imgBgr->imageSize=%d.\n",imgBgr->imageSize);
cvCvtColor(img, imgBgr, CV_YCrCb2BGR);
scal = cvGet2D(imgBgr,1199,1599);//获取像素点
valY = scal.val[0];
valU = scal.val[1];
valV = scal.val[2];
printf("B=%e, G=%e,R=%e.\n",valY,valU,valV);
printf("cvCvtColor sucess.\n");
cvSaveImage("cap.bmp",imgBgr);
// cvSaveImage("./cap.jpg",imgBgr,0);
/*printf("cvSaveImage sucess.\n");
*/
}
void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,void* dwUser)
{
printf("pyd---(hik_v30)Get data,the size is %d.\n", dwBufSize);
unsigned char pBitmap[50000];
unsigned int pBmpSize;
PLAYRECT hwnd;
hwnd.x=0;
hwnd.y=0;
hwnd.uWidth=0;
hwnd.uHeight=0;
switch (dwDataType)
{
case NET_DVR_SYSHEAD: //系统头
if (!PlayM4_GetPort(&lPort)) //获取播放库未使用的通道号
{
printf("(hik_v30)Get PlayM4_GetPort Error.\n");
break;
}
else
{
printf("(hik_v30)Get PlayM4_GetPort lPort=%d.\n",lPort);
}
//m_iPort = lPort; //第一次回调的是系统头,将获取的播放库port号赋值给全局port,下次回调数据时即使用此port号播放
if (dwBufSize > 0)
{
if (!PlayM4_OpenStream(lPort, (char*)pBuffer, dwBufSize, 1024*1024)) //打开流接口
{
printf("(hik_v30)Get PlayM4_OpenStream Error.\n");
break;
}
else
{
printf("(hik_v30)Get PlayM4_OpenStream Success.\n");
}
if(!PlayM4_SetDecCallBack(lPort,g_DecCBFun))
{
printf("(hik_v30)Get PlayM4_SetDecCallBack Error.\n");
break;
}
else
{
printf("(hik_v30)Get PlayM4_SetDecCallBack Success.\n");
}
if (!PlayM4_Play(lPort, hwnd)) //播放开始
{
printf("(hik_v30)Get PlayM4_Play Error.\n");
break;
}
else
{
printf("(hik_v30)Get PlayM4_Play Success.\n");
}
}
break;
case NET_DVR_STREAMDATA: //码流数据
// if(PlayM4_GetBMP(lPort,pBitmap,1024*1024,&pBmpSize))
// {
// printf("(hik_v30)Get PlayM4_GetBMP Bmp Size = %d.\n", pBmpSize);
// }
// else
// {
// printf("(hik_v30)Get PlayM4_GetBMP Error =%d.",PlayM4_GetLastErrorCode());
// }
if (dwBufSize > 0 && lPort != -1)
{
if (!PlayM4_InputData(lPort, (char*)pBuffer, dwBufSize))
{
printf("(hik_v30)Get PlayM4_InputData Error.\n");
break;
}
else
{
printf("(hik_v30)Get PlayM4_InputData success.\n");
}
}
break;
}
}
void CALLBACK g_HikDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,DWORD dwUser)
{
printf("pyd---(hik)Get data,the size is %d.\n", dwBufSize);
}
void CALLBACK g_StdDataCallBack(int lRealHandle, unsigned int dwDataType, unsigned char *pBuffer, unsigned int dwBufSize, unsigned int dwUser)
{
printf("pyd---(rtsp)Get data,the size is %d.\n", dwBufSize);
}
/*******************************************************************
Function: Demo_GetStream
Description: preview(no "_V30")
Parameter: (IN) none
Return: 0--successful,-1--fail。
**********************************************************************/
int Demo_GetStream()
{
NET_DVR_Init();
long lUserID;
//login
NET_DVR_DEVICEINFO struDeviceInfo;
lUserID = NET_DVR_Login("172.2.87.106", 8000, "admin", "12345", &struDeviceInfo);
if (lUserID < 0)
{
printf("pyd1---Login error, %d\n", NET_DVR_GetLastError());
return HPR_ERROR;
}
//Set callback function of getting stream.
long lRealPlayHandle;
NET_DVR_CLIENTINFO ClientInfo = {0};
#if (defined(_WIN32) || defined(_WIN_WCE))
ClientInfo.hPlayWnd = NULL;
#elif defined(__linux__)
ClientInfo.hPlayWnd.x = 0;
ClientInfo.hPlayWnd.y = 0;
ClientInfo.hPlayWnd.uHeight = 0;
ClientInfo.hPlayWnd.uWidth = 0;
#endif
ClientInfo.lChannel = 1; //channel NO
//ClientInfo.lLinkMode = 0x40000000; //Record when breaking network.
ClientInfo.lLinkMode = 0;
ClientInfo.sMultiCastIP = NULL;
lRealPlayHandle = NET_DVR_RealPlay(lUserID, &ClientInfo);
if (lRealPlayHandle < 0)
{
printf("pyd1---NET_DVR_RealPlay_V30 error\n");
NET_DVR_Logout(lUserID);
NET_DVR_Cleanup();
return HPR_ERROR;
}
//Set callback function of getting stream.
int iRet;
iRet = NET_DVR_SetRealDataCallBack(lRealPlayHandle, g_HikDataCallBack, 0);
if (!iRet)
{
printf("pyd1---NET_DVR_RealPlay_V30 error\n");
NET_DVR_StopRealPlay(lRealPlayHandle);
NET_DVR_Logout(lUserID);
NET_DVR_Cleanup();
return HPR_ERROR;
}
#ifdef _WIN32
Sleep(5000); //millisecond
#elif defined(__linux__)
sleep(500); //second
#endif
//stop
NET_DVR_StopRealPlay(lRealPlayHandle);
NET_DVR_Logout(lUserID);
NET_DVR_Cleanup();
return HPR_OK;
}
void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
{
char tempbuf[256] = {0};
switch(dwType)
{
case EXCEPTION_RECONNECT: //预览时重连
printf("pyd----------reconnect--------%d\n", time(NULL));
break;
default:
break;
}
};
/*******************************************************************
Function: Demo_GetStream_V30
Description: preview(_V30)
Parameter: (IN) none
Return: 0--successful,-1--fail。
**********************************************************************/
int Demo_GetStream_V30()
{
NET_DVR_Init();
//设置连接时间,与重连时间
NET_DVR_SetConnectTime(2000, 1);
NET_DVR_SetReconnect(10000, true);
long lUserID;
//login
NET_DVR_DEVICEINFO_V30 struDeviceInfo;
//lUserID = NET_DVR_Login_V30("172.2.87.106", 8000, "admin", "12345", &struDeviceInfo);
//lUserID = NET_DVR_Login_V30("113.18.11.162", 8000, "admin", "12345", &struDeviceInfo);
lUserID = NET_DVR_Login_V30("192.168.1.64", 8000, "admin", "12345", &struDeviceInfo);
if (lUserID < 0)
{
printf("pyd1---Login error, %d\n", NET_DVR_GetLastError());
return HPR_ERROR;
}
NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);
//Set callback function of getting stream.
long lRealPlayHandle;
NET_DVR_CLIENTINFO ClientInfo = {0};
#if (defined(_WIN32) || defined(_WIN_WCE))
ClientInfo.hPlayWnd = NULL;
#elif defined(__linux__)
ClientInfo.hPlayWnd.x = 0;
ClientInfo.hPlayWnd.y = 0;
ClientInfo.hPlayWnd.uHeight = 0;
ClientInfo.hPlayWnd.uWidth = 0;
#endif
ClientInfo.lChannel = 1; //channel NO.
//ClientInfo.lLinkMode = 0x40000000; //Record when breaking network.
ClientInfo.lLinkMode = 0;
ClientInfo.sMultiCastIP = NULL;
lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, g_RealDataCallBack_V30, NULL, 0);
//lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, NULL, NULL, 0);
if (lRealPlayHandle < 0)
{
printf("pyd1---NET_DVR_RealPlay_V30 error\n");
return HPR_ERROR;
}
//Set rtsp callback function of getting stream.
//NET_DVR_SetStandardDataCallBack(lRealPlayHandle, g_StdDataCallBack, 0);
#ifdef _WIN32
Sleep(3000); //millisecond
#elif defined(__linux__)
sleep(100); //second
#endif
//stop
NET_DVR_StopRealPlay(lRealPlayHandle);
NET_DVR_Logout_V30(lUserID);
NET_DVR_Cleanup();
return HPR_OK;
}
这段代码在保存成jpg图片时,会内存溢出。原因是opencv保存jpg文件时要使用libjpeg.so 库的jpeg_start_compress 等函数,
但libm4paly.so也有jpeg_start_compress等函数。程序会找到libm4paly.so中的函数,导致异常。
我的libjpeg.so 库 在/usr/lib下。通过-Wl,-rpath, 选项让程序先找libjpeg.so
g++ -g -lopencv_core -lopencv_highgui -ljpeg -lhcnetsdk -lm4play -o hctest *.cpp -L/usr/local/lib -Wl,-rpath,/usr/lib,-rpath,./
编译后运行,就不会运行异常了。