Quantcast
Channel: Media Foundation Development for Windows Desktop forum
Viewing all articles
Browse latest Browse all 1079

Capture H264 from C920 Problems

$
0
0

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!


Viewing all articles
Browse latest Browse all 1079

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>