DirectX 9 Video Capture
DirectX 9 Video Capture
DirectX 9 Video Capture
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>DirectX</strong> 9<br />
<strong>Video</strong> <strong>Capture</strong><br />
<br />
: http://debut.cis.nctu.edu.tw/~ching
About <strong>Video</strong> <strong>Capture</strong><br />
• describes any application where video is<br />
received from a hardware device<br />
• Cameras, TV tuner cards, video tape<br />
recorders<br />
• the concepts<br />
• Graph Builder<br />
• <strong>Video</strong> <strong>Capture</strong> Devices<br />
• DirectShow <strong>Video</strong> <strong>Capture</strong> Filters
Writing a DirectShow Application<br />
• Three tasks must be performed<br />
1 2 3<br />
立 Filter Graph Manager<br />
利 Filter Graph Manager<br />
立 filter graph<br />
利 Filter Graph Manager<br />
filter graph<br />
When processing is completed,<br />
the application releases the Filter Graph Manager and all of the filters
About the <strong>Capture</strong> Graph Builder<br />
• A Filter graph that perform video & audio<br />
capture<br />
• I<strong>Capture</strong>GraphBuilder2 interface<br />
• Building & controlling a capture graph
<strong>Capture</strong>GraphBuilder2<br />
1<br />
1<br />
Create new instances<br />
1. <strong>Capture</strong> Graph Builder<br />
2. Filter Graph Manager<br />
2<br />
2<br />
立 連 <br />
利 I<strong>Capture</strong>GraphBuilder2::SetFiltergraph<br />
Filter Graph Manager <br />
<strong>Capture</strong> Graph Builder
Create new instances <br />
HRESULT Init<strong>Capture</strong>GraphBuilder(<br />
IGraphBuilder **ppGraph, // <br />
I<strong>Capture</strong>GraphBuilder2 **ppBuild // <br />
) {<br />
IGraphBuilder *pGraph = NULL;<br />
I<strong>Capture</strong>GraphBuilder2 *pBuild = NULL;<br />
1 立 Class ID<br />
// 立 <strong>Capture</strong> Graph Builder.<br />
HRESULT hr = CoCreateInstance(CLSID_<strong>Capture</strong>GraphBuilder2, NULL,<br />
CLSCTX_INPROC_SERVER, IID_I<strong>Capture</strong>GraphBuilder2,<br />
(void**)&pBuild);<br />
DLL <br />
process <br />
行<br />
Interface<br />
Interface<br />
NULL
SetFiltergraph <br />
更 <br />
2<br />
if (SUCCEEDED(hr)) {<br />
// 立 Filter Graph Manager<br />
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,<br />
IID_IGraphBuilder, (void**)&pGraph);<br />
if (SUCCEEDED(hr)) {<br />
pBuild->SetFiltergraph(pGraph);<br />
: SDK <br />
pBuilder 理 <br />
Filter Graph Manager<br />
}<br />
*ppBuild = pBuild;<br />
*ppGraph = pGraph;<br />
return S_OK;<br />
}<br />
else<br />
pBuild->Release();<br />
}<br />
return hr; // Failed<br />
料
<strong>Capture</strong> Filters <br />
• Pin Categories<br />
• 2 更 料 output pins<br />
• Pins 類 , GUID 來 Identify<br />
• Preview Pins & <strong>Capture</strong> Pins<br />
• Preview Pins render video to the screen<br />
• drop frame<br />
• PIN_CATEGORY_PREVIEW<br />
• <strong>Capture</strong> Pins video <br />
• frame time-stamped<br />
• PIN_CATEGORY_CAPTURE<br />
Pin Category<br />
Pin Category
<strong>Capture</strong> Filters <br />
• <strong>Video</strong> Port Pins<br />
• a hardware connection ( video card video<br />
device)<br />
• video device 料 graph<br />
card, hardware overlay <br />
<br />
video memory, CPU<br />
• <br />
• overlay surface<br />
• Frame Flipping .<br />
• Pin category: PIN_CATEGORY_VIDEOPORT
Selecting a <strong>Capture</strong> Device<br />
• 料 , 料<br />
Step 1<br />
利 <br />
System Device Enumerator<br />
料 列 <br />
Step 1<br />
IMoniker<br />
Step 2<br />
Step 2<br />
<br />
利 列 IMoniker 料 <br />
* BindToStorage method : 讀 <br />
* BindToObject method : 立 Filter
例 說<br />
#include // for ATL 7.0 串 <br />
#include // for DirectShow header file<br />
#pragma comment( lib, "Strmiids.lib" ) // for DirectShow library file<br />
#include // for printf<br />
void Enumerate<strong>Video</strong>InputDevice();<br />
int main() {<br />
// Step 1: initial COM<br />
CoInitialize(NULL);<br />
// Step 2: 列 ( 見 )<br />
Enumerate<strong>Video</strong>InputDevice();<br />
}<br />
// COM must be uninitialized<br />
CoUninitialize();<br />
return 0;<br />
<strong>Video</strong> <strong>Capture</strong> Device
void Enumerate<strong>Video</strong>InputDevice(){<br />
ICreateDevEnum *pDevEnum = NULL;<br />
列 <br />
// Step 1: 立 System Device Enumerator <br />
Moniker 立 CLSID ( GUID)<br />
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,<br />
CLSCTX_INPROC_SERVER,<br />
IID_ICreateDevEnum,<br />
reinterpret_cast(&pDevEnum));<br />
IEnumMoniker *pEnum = NULL;<br />
if (SUCCEEDED(hr)){<br />
Non-aggregation<br />
立<br />
Moniker 列 <br />
// Step 2: 立 <strong>Video</strong> capture 列 ( 列 <strong>Video</strong> Input Filter)<br />
hr = pDevEnum->CreateClassEnumerator( \<br />
CLSID_<strong>Video</strong>InputDeviceCategory,\<br />
&pEnum, 0);<br />
}<br />
* CLSID: A globally unique identifier (GUID) associated with an OLE class object. <strong>Video</strong>InputDevice<br />
•aggregation: 立 , Interface exposed.<br />
* Filter Categories 更 Filter
Step 3: 利 列 Next method Moniker , <br />
IMoniker *pMoniker = NULL;<br />
while (pEnum->Next (1, &pMoniker, NULL) == S_OK) {<br />
IPropertyBag *pPropBag;<br />
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,<br />
(void**)(&pPropBag));<br />
if (FAILED(hr)){<br />
pMoniker->Release();<br />
continue;<br />
}<br />
// Step 4: 讀 <br />
VARIANT varName;<br />
VariantInit(&varName);<br />
}<br />
hr = pPropBag->Read (L"FriendlyName", &varName, 0);<br />
if (SUCCEEDED(hr)) {<br />
// OLE 串 TCHAR 串<br />
COLE2T strName(varName.bstrVal);<br />
printf(" = %s \n",strName);<br />
VariantClear(&varName);<br />
}<br />
pPropBag->Release();<br />
pMoniker->Release();<br />
} // end of while<br />
利 Moniker <br />
讀 來<br />
列 <br />
料
立 <strong>Capture</strong> Device Filter<br />
利 Moniker 立<br />
<br />
IBaseFilter 來 <br />
<br />
IBaseFilter *pCap = NULL;<br />
hr = pMoniker->BindToObject (0, 0, IID_IBaseFilter, (void**)&pCap);<br />
Binding<br />
<br />
<br />
<br />
串 Moniker,<br />
left ()<br />
NULL<br />
, Graph Filter <br />
hr = m_pGraph->AddFilter(pCap, L"<strong>Capture</strong> Filter");
Previewing <strong>Video</strong><br />
Step 1: initial COM<br />
Step 2: 立<br />
Graph Manager<br />
Build help Ojbect<br />
Step 3: <br />
<strong>Video</strong> <strong>Capture</strong> Device Filter<br />
Step 4: 立 Graph Filter<br />
Graph<br />
Step 5: 行 Graph Filter
<strong>Video</strong>Render(this->m_hWnd);<br />
Clear()<br />
<strong>Video</strong> Previewing
<strong>Video</strong>Render <br />
// 數 便 理<br />
IGraphBuilder *pGraph; // Graph<br />
I<strong>Capture</strong>GraphBuilder2 *pBuild; // <strong>Capture</strong> Graph Builder<br />
IBaseFilter *pCap; // <strong>Capture</strong> Filter<br />
IMediaControl *pControl; // Graph Controller<br />
int <strong>Video</strong>Render(HWND hwnd) {<br />
// Step 1: initial COM<br />
CoInitialize(NULL);<br />
// Step 2: 立 Graph Manager Build help Ojbect<br />
Init<strong>Capture</strong>GraphBuilder(&pGraph,&pBuild);<br />
// Step 3: <strong>Video</strong> <strong>Capture</strong> Device<br />
Enumerate<strong>Video</strong>InputDevice(&pCap);<br />
pGraph->AddFilter(pCap,L"<strong>Capture</strong> Filter");
Step 4: Graph Builder 立 graph filter <br />
HRESULT hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW ,<br />
&MEDIATYPE_<strong>Video</strong>,<br />
連 pCap Render<br />
pCap, NULL, NULL);<br />
source<br />
Render<br />
// Step 5: 立 來 行 graph filter<br />
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);<br />
pControl->Run();<br />
return 0;<br />
}<br />
<br />
sink<br />
pCap preview<br />
類 pin 料<br />
pCap <br />
<strong>Video</strong><br />
// Release everything<br />
void Clear(){<br />
pGraph->Release();<br />
pCap->Release();<br />
pBuild->Release();<br />
pControl->Release();<br />
filter<br />
}<br />
// COM must be uninitialized<br />
CoUninitialize();
Media File 讀 frame<br />
• 利 Media Detector object (MediaDet) <br />
media file frame<br />
• 利 helper object<br />
• file seekable, <br />
• 不 Filter Manager 立 filter graph,<br />
Media Detector <br />
• Media Detector 利 Sample Grabber<br />
Filter. 料
利 Media Detector <br />
流 <br />
Step 1:<br />
利 ATL Smart Pointer<br />
理 IMediaDet <br />
Step 2: 立 MediaDet <br />
// 1.<br />
CComPtr pDet;<br />
<br />
<br />
Media<br />
Media<br />
Detector<br />
Detector<br />
Object<br />
Object<br />
// 2.<br />
hr = pDet.CoCreateInstance(__uuidof(MediaDet));<br />
if (FAILED(hr)) return hr;<br />
// 3.<br />
CComBSTR bstrFilename(pszFileName);<br />
hr = pDet->put_Filename(bstrFilename);<br />
if (FAILED(hr)) return hr;<br />
media file<br />
Step 3: source file
Stream<br />
了<br />
Source File 了 , <br />
<br />
stream<br />
Step 4:<br />
Media file <br />
stream 數 量<br />
Step 5:<br />
<br />
<strong>Video</strong> stream<br />
stream 數 量<br />
long lStreams;<br />
bool bFound = false;<br />
hr = pDet->get_OutputStreams(&lStreams);<br />
if (FAILED(hr)) return hr;<br />
for (long i = 0; i < lStreams; i++) {<br />
stream<br />
GUID major_type;<br />
hr = pDet->put_CurrentStream(i); 2<br />
if (SUCCEEDED(hr)){<br />
hr = pDet->get_StreamType(&major_type);<br />
}<br />
if (FAILED(hr)) break;<br />
if (major_type == MEDIATYPE_<strong>Video</strong>) {<br />
bFound = true;<br />
break;<br />
}<br />
}<br />
if (!bFound)<br />
return VFW_E_INVALIDMEDIATYPE;<br />
1<br />
3<br />
stream<br />
<strong>Video</strong> Stream
裡 DirectShow 料<br />
( 料 <strong>Video</strong> frame Audio)<br />
stream <br />
• DirectShow AM_MEDIA_TYPE <br />
filter graph digital media formats<br />
Sample 類 , : video audio<br />
類 , : RGB24 RGB 32 YUV<br />
size (TRUE)<br />
frames key frame (TRUE)<br />
Sample . frame sample size (byte)<br />
不 <br />
Sample 類 不 , 不 <br />
format<br />
Format <br />
Sample Format <br />
參 : <strong>DirectX</strong> SDK: About Media Types
stream <br />
Step 6:<br />
frame <br />
long width = 0, height = 0;<br />
AM_MEDIA_TYPE mt;<br />
hr = pDet->get_StreamMediaType(&mt);<br />
if (SUCCEEDED(hr)) {<br />
Sample <br />
<br />
<br />
MEDIATYPE_<strong>Video</strong>,<br />
MEDIATYPE_<strong>Video</strong>,<br />
<br />
<br />
<br />
VIDEOINFOHEADER<br />
VIDEOINFOHEADER<br />
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(mt.pbFormat);<br />
width = pVih->bmiHeader.biWidth;<br />
height = pVih->bmiHeader.biHeight;<br />
sample<br />
sample<br />
Format<br />
Format<br />
<br />
<br />
}<br />
// frame 度 (top-down DIB = , bottom-up DIB =)<br />
if (height < 0) height *= -1;
frame 料<br />
Step 7:<br />
long size;<br />
int second=15;<br />
()<br />
料 <br />
hr = pDet->GetBitmapBits (second, &size, NULL, width, height);<br />
if (SUCCEEDED(hr)) {<br />
char *pBuffer = new char[size]; // <br />
if (!pBuffer) return E_OUTOFMEMORY;<br />
try {<br />
Frame size<br />
hr = pDet->GetBitmapBits(second, NULL, pBuffer, width,height);<br />
if (SUCCEEDED(hr)) {<br />
// Delete the old image, if any.<br />
if (*ppbmih) delete[] (*ppbmih);<br />
(*ppbmih) = (BITMAPINFOHEADER*) pBuffer;<br />
}<br />
else {<br />
delete [] pBuffer; // frame , buffer <br />
}<br />
}<br />
catch (...) { // 若 exception<br />
delete [] pBuffer;<br />
return E_OUTOFMEMORY;<br />
}<br />
Step 8:<br />
frame bitmap 料<br />
利 <br />
料
來<br />
1 frame<br />
來<br />
Grabing_a_Post_Frame
錄 : Header file<br />
// --------- Direct Show Header File & library -------------<br />
#include <br />
#include // for IMediaDet Interface<br />
#pragma comment( lib, "Strmiids.lib" )<br />
// F:\Program Files\DX9\Samples\C++\DirectShow\BaseClasses <br />
// VC : BaseClass header file 錄<br />
// F:\Program Files\DX9\Samples\C++\DirectShow\BaseClasses<br />
#include <br />
#pragma comment(lib, "F:\\Program<br />
Files\\DX9\\Samples\\C++\\DirectShow\\BaseClasses\\Debug\\Strmbasd.lib" ) // debug<br />
build<br />
// BaseClass Windows Multimedia library , 行<br />
#pragma comment(lib, "Winmm.lib" )<br />
// --------- ATL Smart Pointer<br />
// Active Template Libary (ATL): 列 c++ template classes, 立 <br />
// Common Object Model (COM) <br />
#include <br />
#include // for <br />
2<br />
Direct X<br />
錄<br />
1
mk:@MSITStore:F:\Program%20Files\DX9\Documentation\<strong>DirectX</strong>9\<strong>DirectX</strong>9_c.chm::/directX/htm/usingthesystemdeviceenumerator.ht<br />
錄 :<br />
System Device Enumerator<br />
DirectShow Filter Category
• Windows Media Downloads<br />
• http://msdn.microsoft.com/library/default.asp<br />
url=/downloads/list/winmedia.asp