全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1470
推到 Plurk!
推到 Facebook!

DirectShow抓圖

尚未結案
炎峰
一般會員


發表:7
回覆:9
積分:3
註冊:2011-03-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-08-15 16:39:26 IP:60.244.xxx.xxx 訂閱
 不好意思,之前發的兩次網站都會出錯進不去 >"<
故在重新試一次看看 ~"~

----------------------------------------------------------------------------

各位大大好 :D
小弟專題會用到影像處理
目前已在 VFW 架構下完成主要功能了
礙於速度不佳,我們想要換成 DirectShow 試試看

軟體是 C Builder XE
由於小弟笨拙,DSPack 無法 compiler 成功
於是使用 XE 內建的 DirectShow (可直接 #include )

使用 cppfans 逍遙遊 大大的 BcbPlayCap2010 作為範例修改
已能在 Panel 上顯示畫面

但由於要抓圖下來做處理
我們寫了下面的程式 SampleGrabber (是在已成功連接攝影機、RenderStream後呼叫的程式)

問題在於...
使用 Media Event 的 WaitForCompletion 會卡在那邊,無法往下執行
若使用 Sleep 或不等待,均會出現錯誤 0x80040227

小弟這邊希望能先抓到單圖,後續再去處理連續抓圖、callback 的問題

精簡程式碼如下:


[code cpp]
IVideoWindow * g_pVW;
IMediaControl * g_pMC;
IMediaEventEx * g_pME;
IGraphBuilder * g_pGraph;
ICaptureGraphBuilder2 * g_pCapture;
ISampleGrabber *pGrabber;
HRESULT TForm1::SampleGrabber(void)
{
HRESULT hr;
IBaseFilter *pSG_Filter = NULL;
pGrabber = NULL;
long cbBuffer = 0;
BYTE *pBuffer = new BYTE[cbBuffer];
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSG_Filter);
if (FAILED(hr))
{
Msg(TEXT("Creat Sample Graber com faild! hr=0x%x"), hr);
return hr;
}
hr = g_pGraph->AddFilter(pSG_Filter, L"SampleGrab"); // 將 Sample Grabber 加入 filter graph 中
if (FAILED(hr))
{
Msg(TEXT("Add Filter - DampleGrabber Error! hr=0x%x"), hr);
return hr;
}
IBaseFilter *pNull = NULL;
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pNull);
if (FAILED(hr))
{
Msg(TEXT("Creat NullRenderer com faild! hr=0x%x"), hr);
return hr;
}
hr = g_pGraph->AddFilter(pNull, L"NullRender");
if (FAILED(hr))
{
Msg(TEXT("Add Filter - NullRenderer Error! hr=0x%x"), hr);
return hr;
}
AM_MEDIA_TYPE mt;
HDC hdc = GetDC(NULL);
int iBitDepth = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
memset(&mt, 0, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
switch (iBitDepth)
{
case 8:
mt.subtype = MEDIASUBTYPE_RGB8;
break;
case 16:
mt.subtype = MEDIASUBTYPE_RGB555;
break;
case 24:
mt.subtype = MEDIASUBTYPE_RGB24;
break;
case 32:
mt.subtype = MEDIASUBTYPE_RGB32;
break;
default:
return E_FAIL;
}
hr = pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);
if (FAILED(hr))
{
Msg(TEXT("Error @ pSG_Filter->QueryInterface "));
return hr;
}
hr = pGrabber->SetMediaType(&mt);
if (FAILED(hr))
{
Msg(TEXT("Error @ pGrabber->SetMediaType "));
return hr;
}
hr = pGrabber->SetOneShot(false);
if (FAILED(hr))
{
Msg(TEXT("Error @ pGrabber->SetOneShot(FALSE) "));
return hr;
}
hr = pGrabber->SetBufferSamples(true);
if (FAILED(hr))
{
Msg(TEXT("Error @ pGrabber->SetBufferSamples(TRUE) "));
return hr;
}
/* 此處為使用 ISampleGrabberCB::BufferCB
已繼承寫好類似這邊的部分,測試過仍是一樣的問題
因此這邊希望能先抓出單張圖
CSampleGrabberCB g_StillCapCB;
pGrabber->SetCallback(&g_StillCapCB, 1);
// 0 → SampleCB , 傳進來的位址是 Sample 原始資料
// 1 → BufferCB , 傳進來的位址是 Buffer 的資料 */
hr = g_pMC->Run();
if (FAILED(hr))
{
Msg(TEXT("Couldn't run the graph! hr=0x%x"), hr);
return hr;
}
/* 這邊若是使用 Sleep (200~2000 都測過)
則後續 pGrabber->GetCurrentBuffer(&cbBuffer, NULL)
會出現錯誤 hr = 0x80040227 (VFW_E_WRONG_STATE)
若使用 Media Event 的 WaitForCompletion
則是會一直卡在這邊,不會往下執行了 */
//Sleep(200);
long EvCode = 0;
hr = g_pME->WaitForCompletion( INFINITE, &EvCode );
if (FAILED(hr))
{
Msg(TEXT("Couldn't Wait For Completion"));
return hr;
}
hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
if (FAILED(hr))
{
Msg(TEXT("Couldn't Get Current Buffer (NULL)! hr=0x%x"), hr);
return hr;
}
if (!pBuffer)
ShowMessage("pBuffer out of Memory");
hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
if (FAILED(hr))
{
Msg(TEXT("Couldn't Get Current Buffer! hr=0x%x"), hr);
return hr;
}
hr = pGrabber->GetConnectedMediaType(&mt);
if (FAILED(hr))
{
Msg(TEXT("Couldn't get Connected Media Type "));
return hr;
}
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat;
if ((mt.formattype == FORMAT_VideoInfo) && (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) && (mt.pbFormat != NULL) )
pVih = (VIDEOINFOHEADER*)mt.pbFormat;
else
{
FreeMediaType(mt);
Msg(TEXT("Couldn't get Video Info Header!"));
return VFW_E_INVALIDMEDIATYPE;
}
HANDLE hf = CreateFile(L"tmp.bmp", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL );
if( hf == INVALID_HANDLE_VALUE )
return E_FAIL;
BITMAPFILEHEADER bfh;
memset( &bfh, 0, sizeof( bfh ) );
bfh.bfType = 0x4D42;
bfh.bfSize = sizeof( bfh ) cbBuffer sizeof( BITMAPINFOHEADER );
bfh.bfOffBits = sizeof(BITMAPINFOHEADER) sizeof( BITMAPFILEHEADER );
DWORD Written = 0;
WriteFile( hf, &bfh, sizeof( bfh ), &Written, NULL );
BITMAPINFO bi;
BITMAPINFOHEADER bih;
memset( &bih, 0, sizeof( bih ) );
bih.biSize = sizeof( bih );
bih.biWidth = pVih->bmiHeader.biWidth;
bih.biHeight = pVih->bmiHeader.biHeight;
bih.biPlanes = pVih->bmiHeader.biPlanes;
bih.biBitCount = pVih->bmiHeader.biBitCount;
Written = 0;
WriteFile( hf, &bih, sizeof( bih ), &Written, NULL );
Written = 0;
WriteFile(hf, pBuffer, sizeof( pBuffer ), &Written, NULL);
CloseHandle(hf);
FreeMediaType(mt);
SafeRelease(pSG_Filter);
SafeRelease(pGrabber);
delete stream;
delete tmp;
return S_OK;
}
[/code]

問題就是這樣...
還請大大們指點迷津 :(

如是小弟爬文不力或是犯了低級錯誤請大大們用力鞭 ^^


系統時間:2017-12-18 7:16:14
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!