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

DirectShow 抓圖 (重發)

尚未結案
炎峰
一般會員


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

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-08-09 13:49:26 IP:140.130.xxx.xxx 訂閱
不好意思,上次發的那篇 「DirectShow 抓圖」
不知為何送出後一直無法進去 (內部伺服器錯誤)
因此小弟這邊重發一篇試試,如有不妥的地方麻煩通知下 ^^

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

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