2 years ago

#47387

test-img

Andy

Why do IMFSourceReader::ReadSample block when I change the the camera output format?

I have the following Windows C++ code that I have adapted from: https://alax.info/trac/public/browser/trunk/Utilities/MediaFoundation/VideoCaptureSynchronous/VideoCaptureSynchronous.cpp

More info about the original code: https://alax.info/blog/1835 Thanks to Roman R!

#include <winsdkver.h>
#include <sdkddkver.h>
#include <stdio.h>
#include <tchar.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <atlbase.h>
#include <atlcom.h>

#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfreadwrite.lib")

#define __C ATLENSURE_SUCCEEDED
#define __D ATLENSURE_THROW

static UINT32 g_nIndex = 1;

int main()
{
    __C(MFStartup(MF_VERSION));
    {
        CComPtr<IMFMediaSource> pMediaSource;
        {
            CComPtr<IMFAttributes> pAttributes;
            __C(MFCreateAttributes(&pAttributes, 1));
            __C(pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID));
            CComHeapPtr<IMFActivate*> ppActivates;
            UINT32 nActivateCount = 0;
            __C(MFEnumDeviceSources(pAttributes, &ppActivates, &nActivateCount));
            __D(g_nIndex < nActivateCount, E_INVALIDARG);
            const CComPtr<IMFActivate> pActivate = ppActivates[g_nIndex];
            for (UINT32 nIndex = 0; nIndex < nActivateCount; nIndex++)
                reinterpret_cast<CComPtr<IMFActivate>&>(ppActivates[nIndex]).Release();
            __C(pActivate->ActivateObject(__uuidof(IMFMediaSource), (VOID**)&pMediaSource));
            CComHeapPtr<WCHAR> pszFriendlyName;
            __C(pActivate->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &pszFriendlyName, NULL));
            _tprintf(_T("Friendly Name: %ls\n"), (LPCWSTR)pszFriendlyName);
        }
        CComPtr<IMFSourceReader> pSourceReader;
        __C(MFCreateSourceReaderFromMediaSource(pMediaSource, NULL, &pSourceReader));

        // Start My code
        CComPtr<IMFMediaType> mediaType;
        int index = 4; 
        __C(pSourceReader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, index, &mediaType)); // returns MF_E_NO_MORE_TYPES if index is too large
        __C(pSourceReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, mediaType));
        // End my code

        LONGLONG nBaseTime = 0;
        for (; ; )
        {
            DWORD nStreamIndex;
            DWORD nStreamFlags;
            LONGLONG nTime;
            CComPtr<IMFSample> pSample;
            __C(pSourceReader->ReadSample(MF_SOURCE_READER_ANY_STREAM, 0, &nStreamIndex, &nStreamFlags, &nTime, &pSample));
            nTime -= nBaseTime;
            _tprintf(_T("nStreamIndex %d, nStreamFlags 0x%X, nTime %.3f, pSample 0x%p\n"), nStreamIndex, nStreamFlags, nTime / 1E7, (IMFSample*)pSample);
            if (nStreamIndex == 0 && (nStreamFlags & MF_SOURCE_READERF_STREAMTICK))
            {
                ATLASSERT(!pSample);
                nBaseTime = nTime;
                continue;
            }
        }
    }
    __C(MFShutdown());
    return 0;
}

My changes are within the Start my code/End my code block. Without my changes the code runs fine. With my changes however I only get one NULL sample from ReadSample() and after that it blocks in ReadSample(). The output is:

Friendly Name: M034-WDR
nStreamIndex 0, nStreamFlags 0x100, nTime 65175.109, pSample 0x0000000000000000

I have listed the IMFMediaTypes supported by the camera with some other code and found that it had 8 different native formats out of which I preferred number 4.

How can I select this format and get this code to run?

I tried changing to

 ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM,..)

but that did not help.

c++

windows

ms-media-foundation

0 Answers

Your Answer

Accepted video resources