Windows Media Foundation: IMFCaptureEngine::TakePhoto - long waiting time for sampling

Viewed 984

I am using Window Media Foundation to take a photo in my C++ application. My problem is about the long waiting time for sampling.

The algorithm for taking pictures:

  1. Configure preview (frame size for example 640 x 480)
  2. Start preview
  3. User call a reqest to teke photo
  4. call my method ConfigurePhoto (frame size for example 2560 x 1920)
  5. call IMFCaptureEngine::TakePhoto.
  6. to receive photo aplication uses my class which implement interface IMFCaptureEngineOnSampleCallback. and it waits on call HRESULT STDMETHODCALLTYPE CaptureEngineSampleCB::OnSample(IMFSample *pSample)

    I have got a problem with long time to wait for step 6. Sometimes I wait only one second, but sometimes I wait few minuts. The image on the preview looks stuck at this time.

    Is it possible to shorten the waiting time? Does anyone know what I'm doing wrong? Is better method to capture photo?

Below some code

HRESULT CaptureDevice::ConfigurePhoto(INT resolutionId, ConfigurationType configureType)
{
    HRESULT hr = S_OK;

    {
        IMFCaptureSink *pSink = NULL;
        IMFMediaSink *p = NULL;
        UINT32 width, height;

        // Get a pointer to the photo sink.
        HRESULT hr = m_pEngine->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PHOTO, &pSink);
        if (SUCCEEDED(hr))
        {
            IMFCapturePhotoSink *pPhoto = NULL;
            hr = pSink->QueryInterface(IID_PPV_ARGS(&pPhoto));
            if (SUCCEEDED(hr))
            {
                IMFCaptureSource *pSource;

                hr = m_pEngine->GetSource(&pSource);
                if (SUCCEEDED(hr))
                {
                    IMFMediaType *pMediaType = 0;
                    hr = pSource->GetAvailableDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, resolutionId, &pMediaType);
                    if (SUCCEEDED(hr))
                    {
                        LogMediaType(pMediaType);
                        hr = pSource->SetCurrentDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, pMediaType);
                        if (SUCCEEDED(hr))
                        {
                            if (WaitForMediaTypeChange())
                            {
                                IMFMediaType *pMediaType = 0;
                                //Utils::SafeRelease(&pMediaType);
                                hr = pSource->GetCurrentDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, &pMediaType);
                                if (SUCCEEDED(hr))
                                {
                                    hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &width, &height);

                                    IMFMediaType *pPhotoMediaType = 0;
                                    LONG bufferStride = 0;

                                    //Configure the photo format
                                    hr = Utils::CreateSnapshotMediaTypeForCB(pMediaType, &pPhotoMediaType, bufferStride);

                                    if (SUCCEEDED(hr))
                                    {
                                        //LogMediaType(pPhotoMediaType);

                                        if (SUCCEEDED(hr))
                                        {
                                            hr = pPhoto->RemoveAllStreams();
                                            if (SUCCEEDED(hr))
                                            {

                                                DWORD dwSinkStreamIndex;
                                                // Try to connect the first still image stream to the photo sink
                                                hr = pPhoto->AddStream((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, pPhotoMediaType, NULL, &dwSinkStreamIndex);
                                                if (SUCCEEDED(hr))
                                                {

                                                    hr = pPhoto->SetSampleCallback(m_pSampleCallback);

                                                    if (SUCCEEDED(hr))
                                                    {
                                                        hr = pPhoto->Prepare();
                                                        if (SUCCEEDED(hr))
                                                        {
                                                            if (!WaitForCaptureSinkPrepare())
                                                            {
                                                                hr = E_FAIL;
                                                            }

                                                        }
                                                    }
                                                }
                                            }
                                        }
                                        Utils::SafeRelease(&pPhotoMediaType);

                                    }

                                }
                                Utils::SafeRelease(&pMediaType);

                            }
                            else
                            {
                                hr = E_FAIL;
                            }
                        }
                        Utils::SafeRelease(&pMediaType);
                    }
                    Utils::SafeRelease(&pSource);
                }
                Utils::SafeRelease(&pPhoto);
            }
            Utils::SafeRelease(&pSink);
        }

        /* ... other action */
    }
    return hr;
}



 HRESULT CaptureDevice::CreatePreview(INT previewRresolutionId, HWND hWnd, BOOL mirror)
{
    HRESULT hr = S_OK;
    DWORD dwSinkStreamIndex = 0;
    UINT32 w, h;
    LONG lStride = 0;

    if (m_pPreview == NULL)
    {
        IMFCaptureSink *pSink = NULL;

        hr = m_pEngine->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PREVIEW, &pSink);
        if (SUCCEEDED(hr))
        {
            hr = pSink->QueryInterface(IID_PPV_ARGS(&m_pPreview));
            if (SUCCEEDED(hr))
            {
                //if (m_useDirect3D)
                {
                    hr = m_pPreview->SetMirrorState(mirror);
                    m_previewWnd = PreviewWindow::CreatePreviewWindow(*this, hWnd);
                    hr = m_pPreview->SetRenderHandle(m_previewWnd);
                }

                if (SUCCEEDED(hr))
                {
                    IMFCaptureSource* pSource = NULL;

                    hr = m_pEngine->GetSource(&pSource);
                    if (SUCCEEDED(hr))
                    {
                        IMFMediaType *pMediaType = NULL;

                        // Configure the video format for the preview sink.
                        hr = pSource->GetAvailableDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW, previewRresolutionId, &pMediaType);
                        if (SUCCEEDED(hr))
                        {
                            LogMediaType(pMediaType);
                            //hr = Utils::SetDefaultStride(pMediaType, &lStride);
                            hr = pSource->SetCurrentDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW, pMediaType);
                            if (SUCCEEDED(hr))
                            {
                                WaitForMediaTypeChange();

                                IMFMediaType *pMediaType2 = NULL;
                                hr = Utils::CloneVideoMediaType(pMediaType, MFVideoFormat_RGB24, &pMediaType2);
                                if (SUCCEEDED(hr))
                                {
                                    hr = pMediaType2->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
                                    if (SUCCEEDED(hr))
                                    {

                                        // Connect the video stream to the preview sink.
                                        hr = m_pPreview->AddStream((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW, pMediaType2, NULL, &dwSinkStreamIndex);

                                    }
                                }

                                Utils::SafeRelease(&pMediaType2);
                            }
                        }
                        Utils::SafeRelease(&pMediaType);
                    }
                    Utils::SafeRelease(&pSource);
                }
            }
        }
        Utils::SafeRelease(&pSink);

        if (FAILED(hr))
        {
            Utils::SafeRelease(&m_pPreview);
        }
    }

    return hr;
}

Attributes of the preview stream:

MF_MT_FRAME_SIZE    640 x 480
MF_MT_AVG_BITRATE    110592000
MF_MT_MAJOR_TYPE    MFMediaType_Video
MF_MT_DEFAULT_STRIDE    640
MF_MT_AM_FORMAT_TYPE    {05589F80-C356-11CE-BF01-00AA0055595A}
MF_MT_FIXED_SIZE_SAMPLES    1
MF_MT_FRAME_RATE    30000 x 1001
MF_MT_PIXEL_ASPECT_RATIO    1 x 1
MF_MT_ALL_SAMPLES_INDEPENDENT    1
MF_MT_FRAME_RATE_RANGE_MIN    30000 x 1001
MF_MT_SAMPLE_SIZE    460800
MF_MT_INTERLACE_MODE    2
MF_MT_FRAME_RATE_RANGE_MAX    30000 x 1001
MF_MT_SUBTYPE    MFVideoFormat_NV12

the same as

captionSource->GetAvailableDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW, mediaTypeIndex /* chosen by user index 0*/, &pMediaType);

Attributes of the image stream:

MF_MT_FRAME_SIZE    2560 x 1920
MF_MT_MAJOR_TYPE    MFMediaType_Image
MF_MT_AM_FORMAT_TYPE    {692FA379-D3E8-4651-B5B4-0B94B013EEAF}
MF_MT_ALL_SAMPLES_INDEPENDENT    1
MF_MT_SUBTYPE    {19E4A5AA-5662-4FC5-A0C0-1758028E1057}

The same as

captionSource->GetAvailableDeviceMediaType( (DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, mediaTypeIndex /* chosen by user index 16*/, &pMediaType);
0 Answers
Related