回调函数是将就是通过函数指针调用函数,即将该参数传递给其他函数,在调用该参数时候也自动调用该参数。
#include <iostream>
#include <conio.h>
#include <tisudshl.h>
#include "CmdHelper.h"
#include "Listener.h"
using namespace _DSHOWLIB_NAMESPACE;
// Specify the number of buffers to be used.
////宏定义
#define NUM_BUFFERS 10
int main(int argc, char* argv[])
{
///初始化相机控件的类库
DShowLib::InitLibrary();
///注册程序正常退出时候需要的调用的函数
atexit( ExitLibrary );
///创建采集对象
Grabber grabber;
// Create the GrabberListener object.
// CListener is derived from GrabberListener.
///new CListener()被赋值给指针,在后面调用该函数的时候就会调用该指针
CListener *pListener = new CListener();
if( !setupDeviceFromFile( grabber ) )
{
return -1;
}
// Assign the number of buffers to the cListener object.
pListener->setBufferSize( NUM_BUFFERS );
// Enable the overlay bitmap to display the frame counter in the live video.
/////创建帧数窗口
grabber.getOverlay()->setEnable( true );
// Register the pListener object for the frame ready and
// the overlay callback event.
//创建一个listener 对象
grabber.addListener( pListener, GrabberListener::eFRAMEREADY|
GrabberListener::eOVERLAYCALLBACK );
// Create a FrameTypeInfoArray data structure describing the allowed color formats.
///创建一个数据结构用来表示图像的格式
FrameTypeInfoArray acceptedTypes = FrameTypeInfoArray::createRGBArray();
// Create the frame handler sink
// 创建帧存储
smart_ptr<FrameHandlerSink> pSink = FrameHandlerSink::create( acceptedTypes, NUM_BUFFERS );
// enable snap mode (formerly tFrameGrabberMode::eSNAP).
pSink->setSnapMode( true );
// Apply the sink to the grabber.
grabber.setSinkType( pSink );
grabber.startLive(); // Start the grabber.
pSink->snapImages( NUM_BUFFERS ); // Grab NUM_BUFFERS images.
grabber.stopLive(); // Stop the grabber.
// Save the buffers for which CListener::frameReady() has not been called.
// Since CListener::frameReady() calls Sleep(250), it cannot be called for
// every buffer. Nevertheless, all buffers are copied to the MemBufferCollection.
for( size_t i = 0; i < pListener->m_BufferWritten.size(); i++ )
{
if( !pListener->m_BufferWritten[i] )
{
std::cout << "Buffer " << i << " processed in main()." << std::endl;
pListener->saveImage( pSink->getMemBufferCollection()->getBuffer( i ), i);
}
}
// The CListener object must be unregistered for all events
// before it may be destroyed.
grabber.removeListener( pListener );
// Now, it must be checked whether the CListener object has been unregistered
// for all events.
while( grabber.isListenerRegistered( pListener ) )
{
Sleep( 0 ); // Wait and give pending callbacks a chance to complete.
}
// Now, the application can be sure that no callback methods of pListener
// will be called anymore. It is now safe to delete pListener.
delete pListener;
std::cout << "Press any key to continue!" << std::endl;
std::cin.get();
return 0;
}
listener.h
#include <tisudshl.h>
class CListener : public DShowLib::GrabberListener
{
public:
// Overwrite the GrabberListener methods we need
////在子类中重载父类方法
virtual void overlayCallback( DShowLib::Grabber& caller, smart_ptr<DShowLib::OverlayBitmap> pBitmap, const DShowLib::tsMediaSampleDesc& MediaSampleDesc );
////
virtual void frameReady( DShowLib::Grabber& caller, smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD FrameNumber );
// Save one image and mark it as saved
///c存储一副图像,同时标记这福图像已经存储
void saveImage( smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD currFrame );
// Setup the buffersize.
///计数
void setBufferSize( unsigned long NumBuffers );
std::vector<bool> m_BufferWritten; // array of flags which buffers have been saved.
};
listener.cpp
#include <iostream>
#include "Listener.h"
using namespace DShowLib;
//////////////////////////////////////////////////////////////////////////
/*! The overlayCallback() method draws the number of the current frame. The
frame count is a member of the tsMediaSampleDesc structure that is passed
to overlayCallback() by the Grabber.
*/
void CListener::overlayCallback( Grabber& caller, smart_ptr<OverlayBitmap> pBitmap,
const tsMediaSampleDesc& MediaSampleDesc)
{
char szText[25];
if( pBitmap->getEnable() == true ) // Draw only, if the overlay bitmap is enabled.
{
sprintf( szText,"%04d ", MediaSampleDesc.FrameNumber);
pBitmap->drawText( RGB(255,0,0), 0, 0, szText );
}
}
//////////////////////////////////////////////////////////////////////////
/*! The frameReady() method calls the saveImage method to save the image buffer to disk.
*/
void CListener::frameReady( Grabber& caller, smart_ptr<MemBuffer> pBuffer, DWORD currFrame)
{
std::cout << "Buffer " << currFrame << " processed in CListener::frameReady()." << std::endl;
saveImage( pBuffer, currFrame ); // Do the buffer processing.
::Sleep(250); // Simulate a time expensive processing.
}
//////////////////////////////////////////////////////////////////////////
/*! Initialize the array of bools that is used to memorize, which buffers were processed in
the frameReady() method. The size of the array is specified by the parameter NumBuffers.
It should be equal to the number of buffers in the FrameHandlerSink.
All members of m_BufferWritten are initialized to false.
This means that no buffers have been processed.
*/
void CListener::setBufferSize( unsigned long NumBuffers )
{
m_BufferWritten.resize( NumBuffers, false );
}
//////////////////////////////////////////////////////////////////////////
/*! The image passed by the MemBuffer pointer is saved to a BMP file.
*/
void CListener::saveImage( smart_ptr<MemBuffer> pBuffer, DWORD currFrame)
{
char filename[MAX_PATH];
if( currFrame < m_BufferWritten.size() )
{
sprintf( filename, "image%02i.bmp", currFrame );
saveToFileBMP( *pBuffer, filename );
m_BufferWritten.at( currFrame ) = true;
}
}