Захват и preview изображения с камеры
От: asidden  
Дата: 31.05.07 09:46
Оценка:
Всем привет!

Столкнулся со следующей проблемой — в разрабатываемой программке нужна возможность выбора аватарки пользователя и, соответственно, возможность ее же создания путем захвата изображения с камеры девайса (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;
}


спасибо за любую помощь
Re: Захват и preview изображения с камеры
От: Left2 Украина  
Дата: 31.05.07 10:17
Оценка:
А зачем ты вообще подключаешь WMV энкодер и ASF writer? Попробуй всё это выкинуть.
... << RSDN@Home 1.2.0 alpha rev. 676>>
Re[2]: Захват и preview изображения с камеры
От: asidden  
Дата: 31.05.07 10:43
Оценка:
Здравствуйте, Left2, Вы писали:

L>А зачем ты вообще подключаешь WMV энкодер и ASF writer? Попробуй всё это выкинуть.


Сразу так и пробовал (без wmv-encoder & asg-writer), но вернул все как было, когда увидел, что run виснет
Re[3]: Захват и preview изображения с камеры
От: Left2 Украина  
Дата: 31.05.07 12:26
Оценка:
L>>А зачем ты вообще подключаешь WMV энкодер и ASF writer? Попробуй всё это выкинуть.

A>Сразу так и пробовал (без wmv-encoder & asg-writer), но вернул все как было, когда увидел, что run виснет


А если без куска "Create the still image filter, and connect it to the video capture filter"? Чисто захват видео? Работает?
А если выкинуть ещё и захват видео, оставить только preview?

Да! Что за мобила-то?
... << RSDN@Home 1.2.0 alpha rev. 676>>
Re: Захват и preview изображения с камеры
От: asidden  
Дата: 01.06.07 14:31
Оценка:
Здравствуйте, asidden, Вы писали:

A>Всем привет!


A>Столкнулся со следующей проблемой — в разрабатываемой программке нужна возможность выбора аватарки пользователя и, соответственно, возможность ее же создания путем захвата изображения с камеры девайса (WM5 Pocket PC, VC++ 8/WTL).


A>Сначала прочитал про SHCameraCapture и обрадовался, но радоваться было рано — при вызове данная функция на моем девайсе возвращает E+ACCESSDENIED, которая никак не описана в MSDN. Попробовал запустить пример из WM 5 Pocket PC SDK CeCamera — результат тот же.


A>Затем нашел пример CameraCapture в том же SDK — в нем все работает, так как он работает через DirectShow. Следовательно родилась идея снабдить данный пример возможностью preview и сделать "аналог" CameraCapture в самом приложении.


A>Сдесь столкнулся со следующим: когда вызываю IMediaControl::Run() для построенного графа — он приложение виснет на данном методе с мгновенным убиением потока, откуда этот метод вызывался. Причины понять не могу, и если кто-нить сталкивался с подобным помогите, плз.


A>Мне в принципе нужен функционал только для захвата still image и preview — поэтому я сначала удалил все лишнее, касающееся захвата видео, но когда начал ловить глюк — вернул все назад.


A>спасибо за любую помощь



Всем спасибо — все разрешилось. Если окно куда вы собираетесь выводить preview not visible yet — почти все вызовы методов IMediaControl зависают.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.