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:
- Configure preview (frame size for example 640 x 480)
- Start preview
- User call a reqest to teke photo
- call my method ConfigurePhoto (frame size for example 2560 x 1920)
- call IMFCaptureEngine::TakePhoto.
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);