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

DirectShow 抓圖

尚未結案
炎峰
一般會員


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

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-08-09 00:07:02 IP:220.132.xxx.xxx 訂閱
各位大大好 

小弟專題會使用到影像處理
我們已在 VFW 下做出了主要功能,但是因為速度太慢,想換成 DirectShow 試試看

軟體是 C Builder XE,因為小弟功力不足無法成功 compiler DSPack,因此是直接使用 CB XE 內建的 DirectShow (可直接 #include )

使用 cppfans 逍遙遊 大大的 PlayCap2010 為範例下修改
目前已能在 Panel 上顯示畫面,因為要做處理,我們想要把圖片/Buffer給抓下來
但是畫面只會一直撥放,並無法把圖片存下來 (小弟這邊先求能把單張圖片抓下來,後續再去處理連續抓圖、不同時間之圖)...

精簡程式碼如下:

[code cpp]
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]

問題就如上面說的,希望有大大可以指點迷津
如是小弟爬文不足或是犯了白痴的錯誤,請大大用力鞭吧
系統時間:2024-04-20 6:39:04
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!