Всем привет!
Столкнулся со следующей проблемой — в разрабатываемой программке нужна возможность выбора аватарки пользователя и, соответственно, возможность ее же создания путем захвата изображения с камеры девайса (WM5 Pocket PC, VC++ 8/WTL).
Сначала прочитал про SHCameraCapture и обрадовался, но радоваться было рано — при вызове данная функция на моем девайсе возвращает E+ACCESSDENIED, которая никак не описана в MSDN. Попробовал запустить пример из WM 5 Pocket PC SDK CeCamera — результат тот же.
Затем нашел пример CameraCapture в том же SDK — в нем все работает, так как он работает через DirectShow. Следовательно родилась идея снабдить данный пример возможностью preview и сделать "аналог" CameraCapture в самом приложении.
Сдесь столкнулся со следующим: когда вызываю IMediaControl::Run() для построенного графа — он приложение виснет на данном методе с мгновенным убиением потока, откуда этот метод вызывался. Причины понять не могу, и если кто-нить сталкивался с подобным помогите, плз.
Мне в принципе нужен функционал только для захвата still image и preview — поэтому я сначала удалил все лишнее, касающееся захвата видео, но когда начал ловить глюк — вернул все назад.
Граф строится следующим образом:
HRESULT CGraphManager::CreateCaptureGraphInternal()
{
HRESULT hr = S_OK;
CComVariant varCamName;
CPropertyBag PropBag;
OAEVENT oaEvent;
WCHAR wzDeviceName[ MAX_PATH + 1 ];
CComPtr<IMediaEvent> pMediaEvent;
CComPtr<IGraphBuilder> pFilterGraph;
CComPtr<IBaseFilter> pVideoEncoder;
CComPtr<IBaseFilter> pASFMultiplexer;
CComPtr<IFileSinkFilter> pFileSinkFilter;
CComPtr<IPersistPropertyBag> pPropertyBag;
CComPtr<IDMOWrapperFilter> pWrapperFilter;
CComPtr<IBaseFilter> pImageSinkFilter;
CComPtr<IVideoWindow> pVideoWindow;
//
// Create the capture graph builder and register the filtergraph manager.
//
CHK( m_pCaptureGraphBuilder.CoCreateInstance( CLSID_CaptureGraphBuilder ));
CHK( pFilterGraph.CoCreateInstance( CLSID_FilterGraph ));
CHK( m_pCaptureGraphBuilder->SetFiltergraph( pFilterGraph ));
//
// Create and initialize the video capture filter
//
CHK( m_pVideoCaptureFilter.CoCreateInstance( CLSID_VideoCapture ));
CHK( m_pVideoCaptureFilter.QueryInterface( &pPropertyBag ));
// We are loading the driver CAM1 in the video capture filter.
CHK( GetFirstCameraDriver( wzDeviceName ));
varCamName = wzDeviceName;
if( varCamName.vt != VT_BSTR )
{
ERR( E_OUTOFMEMORY );
}
CHK( PropBag.Write( L"VCapName", &varCamName ));
CHK( pPropertyBag->Load( &PropBag, NULL ));
// Everything succeeded, the video capture filter is added to the filtergraph
CHK( pFilterGraph->AddFilter( m_pVideoCaptureFilter, L"Video Capture Filter Source" ));
////
//// Third step: Create the video encoder DMO, load the WMV9 encoder, and
//// add it to the graph
////
//// Create the video encoder
CHK( pVideoEncoder.CoCreateInstance( CLSID_DMOWrapperFilter ));
CHK( pVideoEncoder.QueryInterface( &pWrapperFilter ));
//// Load the WMV9 DMO
CHK( pWrapperFilter->Init( CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER ));
//// Everything succeeded, let's add the encoder to the graph
CHK( pFilterGraph->AddFilter( pVideoEncoder, L"WMV9 DMO Encoder" ));
////
//// Create the ASF multiplexer and add it to the graph
////
CHK( m_pCaptureGraphBuilder->SetOutputFileName( &MEDIASUBTYPE_Asf, L"\\video1.asf", &pASFMultiplexer, &pFileSinkFilter ));
////
//// Connect the video capture filter, the encoder and the multiplexer together
////
CHK( m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pVideoEncoder, pASFMultiplexer ));
// вот эту строчку добавил я и она должна по идее добавлять preview pin
// если ее закоментить, IMediaControl::Run() работает нормально, still image захватывается, единственное - нет preview window
CHK( m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, NULL) );
//
// Create the still image filter, and connect it to the video capture filter
//
CHK( pImageSinkFilter.CoCreateInstance( CLSID_IMGSinkFilter ));
CHK( pFilterGraph->AddFilter( pImageSinkFilter, L"Still image filter" ));
CHK( m_pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_STILL, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, pImageSinkFilter ));
CHK( pImageSinkFilter.QueryInterface( &m_pImageSinkFilter ));
//
// Prevent the data from flowing into the capture stream
//
CHK( m_pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, 0, 0 ,0,0 ));
//
// Let's get the handle for DShow events. The main loop will listen to both notifications from
// the UI thread and for DShow notifications
//
CHK( pFilterGraph->QueryInterface( IID_IMediaEvent, (void**) &pMediaEvent ));
CHK( pMediaEvent->GetEventHandle( &oaEvent ));
m_handle[1] = (HANDLE) oaEvent;
/// этот код тоже добавил я для настройки preview window
pFilterGraph->QueryInterface(IID_IVideoWindow, (void**)&pVideoWindow);
pVideoWindow->put_Owner((OAHWND)m_hwnd);
pVideoWindow->put_WindowStyle(WS_CHILD);
long width = m_rcClientPreview.right - m_rcClientPreview.left;
long height = m_rcClientPreview.bottom - m_rcClientPreview.top;
pVideoWindow->SetWindowPosition(m_rcClientPreview.left, m_rcClientPreview.top, width, height);
m_fGraphBuilt = TRUE;
NotifyMessage( MESSAGE_GRAPH_CREATED, L"Building the graph succeeded" );
Cleanup:
if( FAILED( hr ))
{
NotifyMessage( MESSAGE_ERROR, L"Builing the graph failed" );
}
return hr;
}
Граф запускается следующим методом:
HRESULT CGraphManager::RunCaptureGraphInternal()
{
HRESULT hr = S_OK;
CComPtr<IGraphBuilder> pGraphBuilder;
CComPtr<IMediaControl> pMediaControl;
CComPtr<IVideoWindow> pVideoWindow;
CComPtr<IMediaEvent> pMediaEvent;
long lWaitResult = 0;
// Let's make sure that the graph has been initialized
if(( m_pCaptureGraphBuilder == NULL ) || ( m_fGraphBuilt == FALSE ))
{
ERR( E_FAIL );
}
// Retrieve the filtergraph off the capture graph builder
CHK( m_pCaptureGraphBuilder->GetFiltergraph( &pGraphBuilder ));
// Get the media control interface, and run the graph
CHK( pGraphBuilder->QueryInterface( &pMediaControl ));
// здесь все тихо зависает...
hr = pMediaControl->Run();
CHK( NotifyMessage( MESSAGE_INFO, L"The Graph is running" ));
Cleanup:
if( FAILED( hr ))
{
NotifyMessage( MESSAGE_ERROR, L"Runing the capture graph failed" );
}
return hr;
}
спасибо за любую помощь