私はDirectShowプログラミングの初心者です。ビデオキャプチャデバイスからフレームを頻繁に(つまり100ミリ秒ごとに)取得するために、サンプルグラバーアプリケーションを作成しようとしています。DirectShowカメラストリームドライバ
私のソースコードは、Windows SDKサンプルで提供されているSampleGrabberアプリケーションに基づいています。
一般に、ドライバは自分のPCのウェブカメラを使ってうまく動作します。しかし、私はAsus T100タブレットで使用する際にいくつか問題があります。この場合、カメラの解像度を設定した後、ConnectFilters機能を使用しようとしているときに「libtbdエラーデータが正しくタグ付けされていません」というエラーが表示されます。私がカメラに設定しようとしている解像度は1280x720で、私はそのデバイスがそれをサポートできることを知っています。
私はキャプチャ機能に関する私のコードの一部を添付しています下:
ICreateDevEnum *pSysDevEnum = 0;
IEnumMoniker *pEnumCams = 0;
IMoniker *pMon = 0;
IBaseFilter *CameraF = 0;
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEventEx *pEvent = NULL;
IBaseFilter *pGrabberF = NULL;
ISampleGrabber *pSGrabber = NULL;
IBaseFilter *pSourceF = NULL;
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
IBaseFilter *pNullF = NULL;
BYTE *pBuffer = NULL;
HRESULT hr;
AM_MEDIA_TYPE mt;
int count = 0;
printf("Statting with capturing\n");
//Device list
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
return false;
// Obtain a class enumerator for the video compressor category.
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEnumCams, 0);
if (hr != S_OK)
return false;
// Enumerate the monikers. to desired device (0,1,2,...)
for (int i = 0; i <= cur_cam; ++i)
{
hr = pEnumCams->Next(1, &pMon, NULL);
if (hr != S_OK)
return false;
}
//Get BaseFilter of chosen camera
hr = pMon->BindToObject(0, 0, IID_IBaseFilter, (void**)&CameraF);
if (hr != S_OK)
return false;
//Create the Filter Graph Manager
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraph));
if (FAILED(hr))
return false;
//Query for the IMediaControl and IMediaEventEx interfaces
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if (FAILED(hr))
return false;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
if (FAILED(hr))
return false;
// Add web camera to graph as source filter (because first?)
hr = pGraph->AddFilter(CameraF, L"Capture Source");
if (hr != S_OK)
return false;
// Create an instance of the Sample Grabber Filter
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pGrabberF));
if (FAILED(hr))
return false;
// Add it to the filter graph.
hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber");
if (FAILED(hr))
return false;
hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pSGrabber));
if (FAILED(hr))
return false;
//Set the Media Type
ZeroMemory(&mt, sizeof(mt));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24 ;
hr = pSGrabber->SetMediaType(&mt);
if (FAILED(hr))
return false;
//Building graph. Connecting Source (CameraF) and Sample Grabber
hr = CameraF->EnumPins(&pEnum);
if (FAILED(hr))
return false;
while (S_OK == pEnum->Next(1, &pPin, NULL))
{
hr = SetResolution(width_, height_, pPin);
if (FAILED(hr))
std::cout << "Failed to set resolution" << std::endl;
hr = ConnectFilters(pGraph, pPin, pGrabberF);
if (SUCCEEDED(hr))
{
std::cout << "Success to Connect Filter Graphs" << std::endl;
break;
}
else{
std::cout << "Failed to Connect Filter Graphs" << std::endl;
}
}
if (FAILED(hr)){
std::cout << "Failed A" << std::endl;
return false;
}
SafeRelease(pPin);
//The following code connects the Sample Grabber to the Null Renderer filter:
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pNullF));
if (FAILED(hr))
return false;
hr = pGraph->AddFilter(pNullF, L"Null Filter");
if (FAILED(hr))
return false;
//ConnectFilters SamplerGrabber and Null Filter
hr = ConnectFilters(pGraph, pGrabberF, pNullF);
if (FAILED(hr))
return false;
hr = pSGrabber->SetBufferSamples(TRUE);
if (FAILED(hr))
return false;
hr = pSGrabber->SetOneShot(TRUE);//Halt after sample received
if (FAILED(hr))
return false;
hr = pControl->Run();//Run filter graph
if (FAILED(hr))
return false;
printf("Wait for a seconds to let cam sensor adopt to light\n");
Sleep(3000);//Wait 3 seconds
printf("OK\n");
//char filename[50];
printf("Go for the loop");
for (;;){
long evCode;
while (1)
{
hr = pEvent->WaitForCompletion(INFINITE, &evCode);//Wait for frame
if (evCode == EC_COMPLETE || evCode == EC_SYSTEMBASE)
break;
printf("Not complete. event: %d\n", evCode);
pControl->Pause();//pause the Graph
pSGrabber->SetOneShot(TRUE);//Set to halt after first frame
hr = pControl->Run();//resume filter graph
if (FAILED(hr))
return false;
Sleep(1000);//wait for a second
}
printf("out of while loop");
//if (hr != S_OK)
// return false;
Sleep(100);
//there frame got. Graph still running, but Sample Grabber halted
// Find the required buffer size.
long cbBufSize;
hr = pSGrabber->GetCurrentBuffer(&cbBufSize, NULL);
if (FAILED(hr))
return false;
pBuffer = (BYTE*)CoTaskMemAlloc(cbBufSize);
if (!pBuffer)
{
hr = E_OUTOFMEMORY;
return false;
}
hr = pSGrabber->GetCurrentBuffer(&cbBufSize, (long*)pBuffer);
if (FAILED(hr))
return false;
hr = pSGrabber->GetConnectedMediaType(&mt);
if (FAILED(hr))
return false;
// Examine the format block.
if ((mt.formattype == FORMAT_VideoInfo) &&
(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) && (mt.pbFormat != NULL))
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat;
//sprintf_s(filename, sizeof(filename), "photo%d.bmp",++count);
time_t t1 = time(NULL);
SYSTEMTIME st;
GetSystemTime(&st);
printf("Save frame to file: %s - %02ld,%02ld.%03ld seconds\n", FileName, st.wMinute,st.wSecond, st.wMilliseconds);
hr = WriteBitmap(FileName, &pVih->bmiHeader, mt.cbFormat - SIZE_PREHEADER,pBuffer, cbBufSize);
}
else
{
// Invalid format.
hr = VFW_E_INVALIDMEDIATYPE;
printf("Invalid frame format\n");
}
CoTaskMemFree(pBuffer);
if ((GetAsyncKeyState(VK_ESCAPE) & 0x01))
break;
else if ((GetAsyncKeyState(VK_SPACE) & 0x01))
CameraProperties(CameraF);
}
SafeRelease(pEnum);
SafeRelease(pNullF);
SafeRelease(pSourceF);
SafeRelease(pSGrabber);
SafeRelease(pGrabberF);
SafeRelease(pControl);
SafeRelease(pEvent);
SafeRelease(pGraph);
以下は、カメラの解像度を設定する関数です:
// Set the grabbing size
// First we iterate through the available media types and
// store the first one that fits the requested size.
// If we have found one, we set it.
// In any case we query the size of the current media type
// to have this information for clients of this class.
HRESULT hr;
IAMStreamConfig *pConfig;
IEnumMediaTypes *pMedia;
AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL;
hr = pPin->EnumMediaTypes(&pMedia);
if (SUCCEEDED(hr))
{
while (pMedia->Next(1, &pmt, 0) == S_OK)
{
if (pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat;
// printf("Size %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight);
if (vih->bmiHeader.biWidth == width_ && vih->bmiHeader.biHeight == height_)
{
pfnt = pmt;
printf("found mediatype with %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight);
break;
}
DeleteMediaType(pmt);
}
}
pMedia->Release();
}
hr = pPin->QueryInterface(IID_IAMStreamConfig, (void **)&pConfig);
if (SUCCEEDED(hr))
{
if (pfnt != NULL)
{
hr = pConfig->SetFormat(pfnt);
DeleteMediaType(pfnt);
}
hr = pConfig->GetFormat(&pfnt);
if (SUCCEEDED(hr))
{
m_nWidth = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biWidth;
m_nHeight = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biHeight;
DeleteMediaType(pfnt);
}
}
誰もが前に、この種の問題に直面しました?キャプチャフィルタ設定に間違いはありますか?
いずれのアイデアも非常に役に立ちます。
更新1
私はアプリケーション実行出力のスクリーンショットを追加しています。 Output
UPDATE 2
私はOpenCVの3.1を使用して解像度を設定しようとしましたが、私は正確に同じ問題を抱えていました。タブレットでは、カメラのインテル(R)イメージングシグナルプロセッサ2400ドライバを使用しています。これが問題の場所です。奇妙なのは、AmCapを使用すると、カメラの解像度を設定して問題なくカメラのデバイスを操作できることです。誰か助けてもらえますか? AmCapがカメラとの通信にどのようなインターフェースを使用しているかは誰にも分かりますか?
エラーメッセージはDirectShowに属しません。どのメソッドがそれを与えるのか、それともメッセージボックスですか? Asusソフトウェアの問題とよく似ています。 –
こんにちは、あなたの答えをありがとう。カメラの解像度を設定し、派生したフィルタをグラフに接続しようとしているところでこのエラーが発生します。 'SetResolution(width_、height_、pPin); hr = ConnectFilters(pGraph、pPin、pGrabberF); ' – mike1821
@ mike1821このエラーはどのようにして得られますか?スクリーンショットを表示できますか? – wimh