Hey all,
I am trying to capture the H264 stream from a Logitech C920. First I ran into an issue that the MediaType (IMFMediaType) was not visable via the GetAvailableDeviceMediaType method. With a bit of diggin I resolved this issue. Turns out it was Logitechs 'proprietary' driver that was hiding it from the user. After switching back to the UVC 1.5 driver i now get h64 Media types listed when enumerating the device.
My first issue is that no matter what media type I select and set using the below code, I always just receive the default output on the screen. My hunch is that I have absolutely no clue what I am supposed to be doing and am changing the wrong settings. I am running the CaptureEngine sample code that is provided in the Windows 8.1 SDK samples (can't link as I am un verified but a quick google search should get you there)
I have modified the Capture.cpp HRESULT CaptureManager::StartPreview() method as such:
HRESULT CaptureManager::StartPreview() { if (m_pEngine == NULL) { return MF_E_NOT_INITIALIZED; } if (m_bPreviewing == true) { return S_OK; } IMFCaptureSink *pSink = NULL; IMFMediaType *pMediaType = NULL; DWORD pdwStreamCount = 0; DWORD dwMediaTypeIndex = 0; IMFMediaType *pMediaTypeTemp = NULL; IMFMediaType *pMediaTypeh264 = NULL; IMFMediaType *pMediaType2 = NULL; IMFCaptureSource *pSource = NULL; HRESULT hr = S_OK; // Get a pointer to the preview sink. if (m_pPreview == NULL) { hr = m_pEngine->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PREVIEW, &pSink); if (FAILED(hr)) { goto done; } hr = pSink->QueryInterface(IID_PPV_ARGS(&m_pPreview)); if (FAILED(hr)) { goto done; } hr = m_pPreview->SetRenderHandle(m_hwndPreview); if (FAILED(hr)) { goto done; } hr = m_pEngine->GetSource(&pSource); if (FAILED(hr)) { goto done; } //Written by Manu hr = pSource->GetDeviceStreamCount(&pdwStreamCount); if (FAILED(hr)) { goto done; } //This will enumerate through all the availible sources. WORKS! for (int i = 0; i < pdwStreamCount; i++){ dwMediaTypeIndex = 0; hr = S_OK; while (hr == S_OK){ hr = pSource->GetAvailableDeviceMediaType(i, dwMediaTypeIndex, &pMediaTypeTemp); if (i == 0 && dwMediaTypeIndex == 196) hr = pSource->GetAvailableDeviceMediaType(i, dwMediaTypeIndex, &pMediaTypeh264); //Selects H264 1280x720 30FPS dwMediaTypeIndex++; } if (hr != S_OK && hr != MF_E_NO_MORE_TYPES) { goto done; } } // Configure the video format for the preview sink. This should set the default type to the selected above. hr = pSource->SetCurrentDeviceMediaType(0, pMediaTypeh264); if (FAILED(hr)) { goto done; } // I test here what returns and I do not get back what I just set. That is most likely the issue. hr = pSource->GetCurrentDeviceMediaType(0, &pMediaType); if (FAILED(hr)) { goto done; } // With the above result, I try to strong arm it into using H264 by using that type from now. hr = CloneVideoMediaType(pMediaTypeh264, MFVideoFormat_H264, &pMediaType2); if (FAILED(hr)) { goto done; } hr = pMediaType2->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); if (FAILED(hr)) { goto done; } // Connect the video stream to the preview sink. Note that pMediaType2 is cloned from H264. Yet no matter what I set that to (resolution, format, ratio) nothing changes! DWORD dwSinkStreamIndex; hr = m_pPreview->AddStream((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW, pMediaType2, NULL, &dwSinkStreamIndex); if (FAILED(hr)) { goto done; } } hr = m_pEngine->StartPreview(); if (!m_fPowerRequestSet && m_hpwrRequest != INVALID_HANDLE_VALUE) { // NOTE: By calling this, on SOC systems (AOAC enabled), we're asking the system to not go // into sleep/connected standby while we're streaming. However, since we don't want to block // the device from ever entering connected standby/sleep, we're going to latch ourselves to // the monitor on/off notification (RegisterPowerSettingNotification(GUID_MONITOR_POWER_ON)). // On SOC systems, this notification will fire when the user decides to put the device in // connected standby mode--we can trap this, turn off our media streams and clear this // power set request to allow the device to go into the lower power state. m_fPowerRequestSet = (TRUE == PowerSetRequest(m_hpwrRequest, PowerRequestExecutionRequired)); } done: SafeRelease(&pSink); SafeRelease(&pMediaType); SafeRelease(&pMediaType2); SafeRelease(&pSource); return hr; }
Follow my comments for the issue but basically no matter what I do I cannot change the output (occasionally I am able to break it!). I think I must be calling the wrong functions or doing something fundamentally wrong.
As a part two of this issue: My final goal is to stream this to RSTP (or any network video stream protocol). Is this a good starting point? Are there better approaches?
Cheers in advance!