http://www.cnblogs.com/mlj318/p/3782534.html
dshow,Sample Grabber 从摄像头采集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
char
* CCameraDS::QueryFrame()
{
long
evCode, size = 0;
#if CALLBACKMODE
static
double
lastSampleTime=0;
if
( lastSampleTime == cbInfo.dblSampleTime)
return
NULL;
if
(cbInfo.lBufferSize == 0)
return
NULL;
if
( m_nBufferSize != cbInfo.lBufferSize)
{
if
(m_pFrame)
{
free
(m_pFrame);
}
m_nBufferSize = cbInfo.lBufferSize;
m_pFrame = (
char
*)
malloc
(m_nBufferSize);
//cvCreateImage(cvSize(m_nWidth, m_nHeight), IPL_DEPTH_8U, 3);
}
lastSampleTime = cbInfo.dblSampleTime;
m_pFrame2 = (
char
*)cbInfo.pBuffer;
#else
m_pMediaControl->Run();
m_pMediaEvent->WaitForCompletion(INFINITE, &evCode);
m_pSampleGrabber->GetCurrentBuffer(&size, NULL);
if
(size == 0)
return
NULL;
//if the buffer size changed
if
(size != m_nBufferSize)
{
if
(m_pFrame)
{
free
(m_pFrame);
}
if
(m_pFrame2)
{
free
(m_pFrame2);
}
m_nBufferSize = size;
m_pFrame = (
char
*)
malloc
(m_nWidth*m_nHeight*3);
//cvCreateImage(cvSize(m_nWidth, m_nHeight), IPL_DEPTH_8U, 3);
m_pFrame2 = (
char
*)
malloc
(m_nWidth*m_nHeight*3);
}
m_pSampleGrabber->GetCurrentBuffer(&m_nBufferSize, (
long
*)m_pFrame2);
//cvFlip(m_pFrame);
#endif
for
(
int
i=0;i<m_nHeight;i++)
memcpy
(m_pFrame+m_nWidth*3*i,m_pFrame2+m_nWidth*3*(m_nHeight-1-i),m_nWidth*3);
return
m_pFrame;
}
|
1.缓冲区模式
#if !CALLBACKMODE
m_pSampleGrabber->SetBufferSamples(TRUE);
m_pSampleGrabber->SetOneShot(TRUE);
#endif
只能设置SetOneShot为TRUE, 因为使用SetPositions 函数始终返回 E_NOTIMPL:Method is not supported.如果为false,
1
|
WaitForCompletion(INFINITE, &evCode)函数会一直等待下去。
|
2.回调模式
回调模式每采到一直就会进入回调函数,可以在回调函数里面处理采到的数据。
#if CALLBACKMODE
m_pSampleGrabber->SetBufferSamples(FALSE);
m_pSampleGrabber->SetOneShot(FALSE);
// Set the callback, so we can grab the one sample
//
CB.Width = m_nWidth;
CB.Height = m_nHeight;
hr = m_pSampleGrabber->SetCallback( &CB, 1 );
m_pMediaControl->Run();
#endif
只用Run()一次即可。如果SetOneShot(TRUE)的话,也可以每请求一帧Run()一次,然后WaitForCompletion,再从回调函数的buffer中取出数据,这种其实和缓冲区模式一样,只不过缓冲区变成了在回调函数中。
如果摄像头采集帧率为30,SetOneShot(FALSE)回调模式,就一秒进去回调函数30次。而OneShot模式会取到重复的帧。