Ilya
Ilya

Reputation: 93

IAMVideoProcAmp GetRange only works after delay (C++)?

I have an issue trying to control camera parameters. Here is the function to set brightness parameter (I am extending the code from Windows Media Foundation recording audio) :

HRESULT deviceInput::SetupCamera(UINT32 deviceID) {
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
IMFActivate* device = this->getDevice(deviceID);
if (device == NULL)
    return E_FAIL;
IMFMediaSource* pCameraSource = NULL;
HRESULT hr = (m_devices[deviceID])->ActivateObject(IID_PPV_ARGS(&pCameraSource));
if (FAILED(hr)) {
    wcout << "Could not activate object" << endl;
    return hr;
}
IAMVideoProcAmp* spVideo = NULL;
hr = CoCreateInstance(__uuidof(IMFMediaSource) , NULL, CLSCTX_INPROC_SERVER, __uuidof(IAMVideoProcAmp),
                      reinterpret_cast<void**>(&spVideo));  
hr = pCameraSource->QueryInterface(IID_PPV_ARGS(&spVideo));
if(FAILED(hr)) {
    wcout << "Could not get interface" << endl;
    return hr;
}
if(spVideo) {
    wcout << "Getting brightness" << endl;
    long Min, Max, step, def, control;
    Sleep(100); // if I remove this - will get "Element not found error"
    hr = spVideo->GetRange(VideoProcAmp_Brightness, &Min, &Max, &step, &def, &control);
    if (SUCCEEDED(hr))
        wcout << "Brightness. Min = " << Min <<", max = " << Max << endl;
    else {
        _com_error err(hr);
        LPCTSTR errMsg = err.ErrorMessage();
        wcout << "Failed: " << errMsg << endl;
    }
}
CoUninitialize();
return hr;
}

It seems I need to insert a pause before calling GetRange() method, otherwise I am getting "Element not found" error. QueryInterface works correctly, since I am checking HRESULT value, and spVideo gets populated regardless of the delay. Does anyone know how to get this to work without inserting arbitrary delays?

Upvotes: 2

Views: 609

Answers (1)

Evgeny Pereguda
Evgeny Pereguda

Reputation: 583

you described well known problem. The fact is that after execution of activating system needs time for initializing driver for camera. It needs time. If you really want to remove Sleep function then you should call camera properties via DeviceIoControl On MSDN USB Video Class Properties you find the next text "Call KsSynchronousDeviceControl or DeviceIoControl to make property requests from a user-mode component. DeviceIoControl is documented in the Microsoft Windows SDK documentation." By the way, for using of DeviceIoControl it DOES NOT NEED activate MediaSource. DeviceIoControl function needs only symbolicLink of camera. However, writing code for direct working with driver can be very difficult (I wrote it in one C++ class).

Upvotes: 1

Related Questions