locked
Capture H264 from C920 Problems RRS feed

  • Question

  • 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!

    Wednesday, January 22, 2014 4:28 AM

All replies

  • Hello.

    I already used Logitech C920, but under Windows Seven. I could set the mediatype with no problems. I will check your code later, but perhaps, the behaviour is different from Windows Seven to Windows 8.

    Tuesday, January 28, 2014 10:22 PM