视频采集,想加入自己的算法,求教

lcydhr 2014-06-05 01:27:45
淘宝买的网络摄像头,提供了一套SDK,现在我想在DEMO里加入自己的算法,可是不知从哪下手,我的理解是视频在解码后,播放前,是放在某个存储区的,只要找到这个存储区的首地址以及长度,就可以得到每一帧的图像,然后进行处理,不知道这么理解对不对,具体的细节我也不太清楚,以下是相关程序,MFC写的,我找不到解码后的存储区地址,SDK提供的函数不开源,只有很简短的说明。

int CVideoWnd::ConnectRealPlay(DEV_INFO *pDev, int nChannel, bool bOsd)
{
if(m_iPlayhandle != -1)
{
//H264_DVR_DelRealDataCallBack(m_iPlayhandle, RealDataCallBack, (long)this);
H264_DVR_DelRealDataCallBack_V2(m_iPlayhandle, RealDataCallBack_V2, (long)this);
if(!H264_DVR_StopRealPlay(m_iPlayhandle))
{
TRACE("H264_DVR_StopRealPlay fail m_iPlayhandle = %d", m_iPlayhandle);
}
}

if ( m_nPlaydecHandle == -1 )
{
//open decoder
BYTE byFileHeadBuf;
if (H264_PLAY_OpenStream(m_nIndex, &byFileHeadBuf, 1, SOURCE_BUF_MIN*50))
{
//设置信息帧回调
H264_PLAY_SetInfoFrameCallBack(m_nIndex, videoInfoFramCallback,(DWORD)this);

//叠加osd信息
if ( bOsd )
{
OSD_INFO_TXT osd;
osd.bkColor = RGB(0,255,0);
osd.color = RGB(255,0,0);
osd.pos_x = 10;
osd.pos_y = 10;
osd.isTransparent = 0;
strcpy(osd.text, "test osd info");
H264_PLAY_SetOsdTex(m_nIndex, &osd);


OSD_INFO_TXT osd2;
osd2.bkColor = RGB(255,0,0);
osd2.color = RGB(0,255,0);
osd2.pos_x = 10;
osd2.pos_y = 40;
osd2.isTransparent = 0;
osd2.isBold = 1;
strcpy(osd2.text, "test222 osd info");
H264_PLAY_SetOsdTex(m_nIndex, &osd2);


//设置osd叠加回调
H264_PLAY_RigisterDrawFun(m_nIndex, drawOSDCall, (DWORD)this);
}
H264_PLAY_SetStreamOpenMode(m_nIndex, STREAME_REALTIME);
if ( H264_PLAY_Play(m_nIndex, this->m_hWnd) )
{
H264_PLAY_SetDisplayCallBack(m_nIndex, pProc, (LONG)this);
m_nPlaydecHandle = m_nIndex;
}
}
}
H264_DVR_CLIENTINFO playstru;

playstru.nChannel = nChannel;
playstru.nStream = 0; //主码流
playstru.nMode = 0; //TCP方式
m_iPlayhandle = H264_DVR_RealPlay(pDev->lLoginID, &playstru);
if(m_iPlayhandle <= 0 )
{
DWORD dwErr = H264_DVR_GetLastError();
CString sTemp("");
sTemp.Format("access %s channel%d fail, dwErr = %d",pDev->szDevName,nChannel, dwErr);
MessageBox(sTemp);
}
else
{
//set callback to decode receiving data
//H264_DVR_SetRealDataCallBack(m_iPlayhandle, RealDataCallBack, (long)this);
H264_DVR_MakeKeyFrame(pDev->lLoginID, nChannel, 0);
H264_DVR_SetRealDataCallBack_V2(m_iPlayhandle, RealDataCallBack_V2, (long)this);
}
m_lLogin = pDev->lLoginID;
m_iChannel = nChannel;
return m_iPlayhandle;
}

其中H264_DVR_SetRealDataCallBack_V2的函数说明是:设置回调函数,用户自己处理客户端收到的数据;可是我不知道该怎么用,这个函数的返回值是个BOOL值,怎么就收到数据了,数据放在那里了,大家帮帮忙啊
...全文
744 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
倚剑仙 2015-05-17
  • 打赏
  • 举报
回复
延时问题已经解决,采用消息机制和多线程方法
倚剑仙 2015-03-26
  • 打赏
  • 举报
回复
引用 21 楼 congmingmiaoyu 的回复:
哈哈,恰巧我也买了这款摄像头,顺便调试了一下代码。楼主基本上找到了问题的关键,大家也说得差不多了,就差一点了。 void __stdcall pProc(LONG nPort,LPCSTR pBuf,LONG nSize,LONG nWidth,LONG nHeight, LONG nStamp,LONG nType,LONG nUser) { } 就是在这个函数里面处理的。数据头是 pBuf, 长度是nSize, 根据我的调试加说明文档,最后确定了,解码出来的格式是YV12,那么在这里你要先进行格式转换。 bool YV12_to_RGB24(unsigned char* pYV12, unsigned char* pRGB24, int iWidth, int iHeight) { if(!pYV12 || !pRGB24) return false; const long nYLen = long(iHeight * iWidth); const int nHfWidth = (iWidth>>1); if(nYLen < 1 || nHfWidth < 1) return false; unsigned char* yData = pYV12; unsigned char* vData = &yData[nYLen]; unsigned char* uData = &vData[nYLen>>2]; if(!uData || !vData) return false; int rgb[3]; int i, j, m, n, x, y; m = -iWidth; n = -nHfWidth; for(y = 0; y < iHeight; y++) { m += iWidth; if(!(y % 2)) n += nHfWidth; for(x=0; x < iWidth; x++) { i = m + x; j = n + (x>>1); rgb[2] = int(yData[i] + 1.370705 * (vData[j] - 128)); // r分量值 rgb[1] = int(yData[i] - 0.698001 * (uData[j] - 128) - 0.703125 * (vData[j] - 128)); // g分量值 rgb[0] = int(yData[i] + 1.732446 * (uData[j] - 128)); // b分量值 j = nYLen - iWidth - m + x; i = (j<<1) + j; for(j=0; j<3; j++) { if(rgb[j]>=0 && rgb[j]<=255) pRGB24[i + j] = rgb[j]; else pRGB24[i + j] = (rgb[j] < 0) ? 0 : 255; } } } return true; } 转换完之后,想干啥就干啥,用opencv做一个测试: IplImage* pRGBImg = cvCreateImage(cvSize(nWidth,nHeight),8,3); YV12_to_RGB24((BYTE*)pBuf,(BYTE*)pRGBImg->imageData,nWidth,nHeight); cvFlip(pRGBImg,pRGBImg); cvSaveImage("test.jpg",pRGBImg); cvReleaseImage(&pRGBImg); 达到预期效果!
大神,你用这个做出来后视频卡吗?我用你的方法做出来为什么这么卡呢?延时十几秒……
congmingmiaoyu 2015-01-29
  • 打赏
  • 举报
回复
哈哈,恰巧我也买了这款摄像头,顺便调试了一下代码。楼主基本上找到了问题的关键,大家也说得差不多了,就差一点了。 void __stdcall pProc(LONG nPort,LPCSTR pBuf,LONG nSize,LONG nWidth,LONG nHeight, LONG nStamp,LONG nType,LONG nUser) { } 就是在这个函数里面处理的。数据头是 pBuf, 长度是nSize, 根据我的调试加说明文档,最后确定了,解码出来的格式是YV12,那么在这里你要先进行格式转换。 bool YV12_to_RGB24(unsigned char* pYV12, unsigned char* pRGB24, int iWidth, int iHeight) { if(!pYV12 || !pRGB24) return false; const long nYLen = long(iHeight * iWidth); const int nHfWidth = (iWidth>>1); if(nYLen < 1 || nHfWidth < 1) return false; unsigned char* yData = pYV12; unsigned char* vData = &yData[nYLen]; unsigned char* uData = &vData[nYLen>>2]; if(!uData || !vData) return false; int rgb[3]; int i, j, m, n, x, y; m = -iWidth; n = -nHfWidth; for(y = 0; y < iHeight; y++) { m += iWidth; if(!(y % 2)) n += nHfWidth; for(x=0; x < iWidth; x++) { i = m + x; j = n + (x>>1); rgb[2] = int(yData[i] + 1.370705 * (vData[j] - 128)); // r分量值 rgb[1] = int(yData[i] - 0.698001 * (uData[j] - 128) - 0.703125 * (vData[j] - 128)); // g分量值 rgb[0] = int(yData[i] + 1.732446 * (uData[j] - 128)); // b分量值 j = nYLen - iWidth - m + x; i = (j<<1) + j; for(j=0; j<3; j++) { if(rgb[j]>=0 && rgb[j]<=255) pRGB24[i + j] = rgb[j]; else pRGB24[i + j] = (rgb[j] < 0) ? 0 : 255; } } } return true; } 转换完之后,想干啥就干啥,用opencv做一个测试: IplImage* pRGBImg = cvCreateImage(cvSize(nWidth,nHeight),8,3); YV12_to_RGB24((BYTE*)pBuf,(BYTE*)pRGBImg->imageData,nWidth,nHeight); cvFlip(pRGBImg,pRGBImg); cvSaveImage("test.jpg",pRGBImg); cvReleaseImage(&pRGBImg); 达到预期效果!
qq_18591249 2014-08-15
  • 打赏
  • 举报
回复
不知楼主做出来了没有,我现在也在做这个,茫无头绪啊
lcydhr 2014-07-03
  • 打赏
  • 举报
回复
引用 16 楼 fang098 的回复:
[quote=引用 14 楼 lcydhr 的回复:] [quote=引用 13 楼 m617105 的回复:] [quote=引用 10 楼 lcydhr 的回复:] [quote=引用 9 楼 m617105 的回复:] 看错了。 RealDataCallBack_V2回调出来的应该是没有解码的数据。 解码是在播放库里进行的。 播放库的SDK里应该有专门的解码函数。
主要就是没有专门的解码函数 只有一个回调函数,说明是用来处理客户端数据,哎,我的头发哗哗的掉啊[/quote] 你没有SDK说明文档吗? [/quote] 找客服要到说明文档了,可是还是找不到缓冲区地址,555555 有一个函数的说明是这样的: H264_PLAY_SetDisplayCallBack设置的视频数据回调函数,只有在有视频数据解码出来时才调用,并由用户处理视频数据(如抓图),如果不断有解码的数据,就不断调用这个回调函数。 其函数原型为
WORD  H264_PLAY_SetDisplayCallback(
LONG nPort,
DisplayCallBack pDisplayProc,
LONG nUser)
其中pDisplayProc为视频图像显示数据回调函数,在程序中实际函数名是pProc,如下
H264_PLAY_SetDisplayCallBack(m_nIndex, pProc, (LONG)this);
可是这个函数却是空的,
void __stdcall pProc(LONG nPort,LPCSTR pBuf,LONG nSize,LONG nWidth,LONG nHeight, LONG nStamp,LONG nType,LONG nUser)
{

}
,到这就卡住了,不知道这个函数怎么用,是干什么用的[/quote] 264解码后出来的数据都告诉你了啊,这个函数是空的就是要你自己去画到你的窗口上,解码出来一般是YUV,具体是YUV什么类型我看到有一个LONG nType,不知道是不是指这个,你要查下资料,要显示YUV如果要省事用SDL库,如果想自己做先转成BMP再自己画。[/quote] 基础差了点,不知道那个函数该怎么个用法,没这个函数的例子,哎,痛苦,还要自己慢慢学
lcydhr 2014-07-03
  • 打赏
  • 举报
回复
引用 15 楼 m617105 的回复:
管他们要Demo吧,Demo里面几乎所有的函数都有例子。 用别人的SDK,一是要文档,二就是要Demo。
好吧,谢谢了,还是我自己基础太差了
baichi4141 2014-07-03
  • 打赏
  • 举报
回复
回调函数就是给你写代码的 你写一个函数,把函数指针输入视频采集控制库,当这个库采集到视频后自动调用你写的这个函数 楼主头发缺失的主要原因,在于不知道什么叫回调函数……
fang 2014-07-03
  • 打赏
  • 举报
回复
引用 14 楼 lcydhr 的回复:
[quote=引用 13 楼 m617105 的回复:] [quote=引用 10 楼 lcydhr 的回复:] [quote=引用 9 楼 m617105 的回复:] 看错了。 RealDataCallBack_V2回调出来的应该是没有解码的数据。 解码是在播放库里进行的。 播放库的SDK里应该有专门的解码函数。
主要就是没有专门的解码函数 只有一个回调函数,说明是用来处理客户端数据,哎,我的头发哗哗的掉啊[/quote] 你没有SDK说明文档吗? [/quote] 找客服要到说明文档了,可是还是找不到缓冲区地址,555555 有一个函数的说明是这样的: H264_PLAY_SetDisplayCallBack设置的视频数据回调函数,只有在有视频数据解码出来时才调用,并由用户处理视频数据(如抓图),如果不断有解码的数据,就不断调用这个回调函数。 其函数原型为
WORD  H264_PLAY_SetDisplayCallback(
LONG nPort,
DisplayCallBack pDisplayProc,
LONG nUser)
其中pDisplayProc为视频图像显示数据回调函数,在程序中实际函数名是pProc,如下
H264_PLAY_SetDisplayCallBack(m_nIndex, pProc, (LONG)this);
可是这个函数却是空的,
void __stdcall pProc(LONG nPort,LPCSTR pBuf,LONG nSize,LONG nWidth,LONG nHeight, LONG nStamp,LONG nType,LONG nUser)
{

}
,到这就卡住了,不知道这个函数怎么用,是干什么用的[/quote] 264解码后出来的数据都告诉你了啊,这个函数是空的就是要你自己去画到你的窗口上,解码出来一般是YUV,具体是YUV什么类型我看到有一个LONG nType,不知道是不是指这个,你要查下资料,要显示YUV如果要省事用SDL库,如果想自己做先转成BMP再自己画。
浩南_哥 2014-07-03
  • 打赏
  • 举报
回复
管他们要Demo吧,Demo里面几乎所有的函数都有例子。 用别人的SDK,一是要文档,二就是要Demo。
lcydhr 2014-07-02
  • 打赏
  • 举报
回复
引用 13 楼 m617105 的回复:
[quote=引用 10 楼 lcydhr 的回复:] [quote=引用 9 楼 m617105 的回复:] 看错了。 RealDataCallBack_V2回调出来的应该是没有解码的数据。 解码是在播放库里进行的。 播放库的SDK里应该有专门的解码函数。
主要就是没有专门的解码函数 只有一个回调函数,说明是用来处理客户端数据,哎,我的头发哗哗的掉啊[/quote] 你没有SDK说明文档吗? [/quote] 找客服要到说明文档了,可是还是找不到缓冲区地址,555555 有一个函数的说明是这样的: H264_PLAY_SetDisplayCallBack设置的视频数据回调函数,只有在有视频数据解码出来时才调用,并由用户处理视频数据(如抓图),如果不断有解码的数据,就不断调用这个回调函数。 其函数原型为
WORD  H264_PLAY_SetDisplayCallback(
LONG nPort,
DisplayCallBack pDisplayProc,
LONG nUser)
其中pDisplayProc为视频图像显示数据回调函数,在程序中实际函数名是pProc,如下
H264_PLAY_SetDisplayCallBack(m_nIndex, pProc, (LONG)this);
可是这个函数却是空的,
void __stdcall pProc(LONG nPort,LPCSTR pBuf,LONG nSize,LONG nWidth,LONG nHeight, LONG nStamp,LONG nType,LONG nUser)
{

}
,到这就卡住了,不知道这个函数怎么用,是干什么用的
lcydhr 2014-06-07
  • 打赏
  • 举报
回复
引用 11 楼 bluesen 的回复:
用OpenCV
本来在学校一直用MATLAB,vc神马的都是现学的,正准备学习CV
bluesen 2014-06-07
  • 打赏
  • 举报
回复
用OpenCV
lcydhr 2014-06-07
  • 打赏
  • 举报
回复
引用 9 楼 m617105 的回复:
看错了。 RealDataCallBack_V2回调出来的应该是没有解码的数据。 解码是在播放库里进行的。 播放库的SDK里应该有专门的解码函数。
主要就是没有专门的解码函数 只有一个回调函数,说明是用来处理客户端数据,哎,我的头发哗哗的掉啊
浩南_哥 2014-06-07
  • 打赏
  • 举报
回复
看错了。 RealDataCallBack_V2回调出来的应该是没有解码的数据。 解码是在播放库里进行的。 播放库的SDK里应该有专门的解码函数。
浩南_哥 2014-06-07
  • 打赏
  • 举报
回复
其实你可以直接联系他们管SDK的。 直接问,自己猜猜到啥时候了去了。 如果你想得到每一帧数据的话,直接改成帧模式就可以了,回调出来的就是一个完整的帧。 RealDataCallBack_V2,第二个参数就是一帧的数据。

typedef struct
{
	int		nPacketType;				// 包类型,见MEDIA_PACK_TYPE
	char*	pPacketBuffer;				// 缓存区地址
	unsigned int	dwPacketSize;				// 包的大小

	// 绝对时标
	int		nYear;						// 时标:年		
	int		nMonth;						// 时标:月
	int		nDay;						// 时标:日
	int		nHour;						// 时标:时
	int		nMinute;					// 时标:分
	int		nSecond;					// 时标:秒
	unsigned int 	dwTimeStamp;					// 相对时标低位,单位为毫秒
	unsigned int	dwTimeStampHigh;        //相对时标高位,单位为毫秒
	unsigned int   dwFrameNum;             //帧序号
	unsigned int   dwFrameRate;            //帧率
	unsigned short uWidth;              //图像宽度
	unsigned short uHeight;             //图像高度
	unsigned int       Reserved[6];            //保留
} PACKET_INFO_EX;
lcydhr 2014-06-07
  • 打赏
  • 举报
回复
引用 6 楼 tiger9991 的回复:
我也没整过类似的。只能扯两句,希望能帮到楼主。 你思路是对的,看看原来SDK是存储区用的是什么数据类型指针,搞过来重新拼接一下。如果本身SDK的的容器指针结构体跟不到的话,确实就很麻烦了。
是的,现在就在找指针,正在研究SDK自带函数
傻X 2014-06-07
  • 打赏
  • 举报
回复
我也没整过类似的。只能扯两句,希望能帮到楼主。 你思路是对的,看看原来SDK是存储区用的是什么数据类型指针,搞过来重新拼接一下。如果本身SDK的的容器指针结构体跟不到的话,确实就很麻烦了。
lcydhr 2014-06-07
  • 打赏
  • 举报
回复
引用 4 楼 xuwentao37x 的回复:
帮楼主顶一个,虽然我也不知道咋办。
多谢兄弟
浩南_哥 2014-06-07
  • 打赏
  • 举报
回复
引用 10 楼 lcydhr 的回复:
[quote=引用 9 楼 m617105 的回复:]
看错了。
RealDataCallBack_V2回调出来的应该是没有解码的数据。
解码是在播放库里进行的。
播放库的SDK里应该有专门的解码函数。
主要就是没有专门的解码函数
只有一个回调函数,说明是用来处理客户端数据,哎,我的头发哗哗的掉啊[/quote]

你没有SDK说明文档吗?
lcydhr 2014-06-06
  • 打赏
  • 举报
回复
祈祷大神降临
加载更多回复(3)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧