13.01.2015 Views

DirectX 9 Video Capture

DirectX 9 Video Capture

DirectX 9 Video Capture

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!