c++ms-media-foundationcritical-sectionopenframeworks

EnterCriticalSection freezes further execution in Release


Im working on an openframeworks extension for Microsoft Media Foundation. My program executes fine in Debug builds but freezes upon the enterCriticalSection call in Release builds.

I don't get any build errors whatsoever. Upon setup of the ofApp in a release build it just hangs in the console forever.

The line Pass 2b is never written to the console.

HRESULT ofxMMF::SetSourceReader(IMFActivate * device) {
    HRESULT hr = S_OK;

    IMFMediaSource * source = NULL;
    IMFAttributes * attributes = NULL;
    std::cout << "Pass 2a" << std::endl;

    EnterCriticalSection(&criticalSection);
    std::cout << "Pass 2b" << std::endl;
    hr = device -> ActivateObject(__uuidof(IMFMediaSource), (void **)&source);
    
    //get symbolic link for the device
    if (SUCCEEDED(hr))
        hr = device ->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &wSymbolicLink, &cchSymbolicLink);
    //Allocate attributes
    if (SUCCEEDED(hr))
        hr = MFCreateAttributes(&attributes, 2);
    //get attributes
    if (SUCCEEDED(hr))
        hr = attributes -> SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, TRUE);
    // Set the callback pointer.
    if (SUCCEEDED(hr))
        hr = attributes -> SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, this);
    //Create the source reader
    if (SUCCEEDED(hr))
        hr = MFCreateSourceReaderFromMediaSource(source, attributes, &sourceReader);
        EnumerateCaptureFormats(source);

    bool foundCorrectMediaType = false;

    // Try to find a suitable output type.
    if (SUCCEEDED(hr)) {
        HRESULT nativeTypeErrorCode = S_OK;
        DWORD count = 0;
        UINT32 streamIndex = 0;
        //2688 x 1512
        UINT32 requiredWidth = reqW;
        UINT32 requiredheight = reqH;

        

        while (nativeTypeErrorCode == S_OK) {
            IMFMediaType * nativeType = NULL;
            nativeTypeErrorCode = sourceReader->GetNativeMediaType(streamIndex, count, &nativeType);
            if (nativeTypeErrorCode != S_OK) continue;

            GUID nativeGuid = { 0 };
            hr = nativeType->GetGUID(MF_MT_SUBTYPE, &nativeGuid);

            if (FAILED(hr)) return hr;

            UINT32 cwidth, cheight;
            hr = MFGetAttributeSize(nativeType, MF_MT_FRAME_SIZE, &cwidth, &cheight);
            if (FAILED(hr)) return hr;

            UINT32 yuv_video_matrix = 0;
            yuv_video_matrix = MFGetAttributeUINT32(nativeType, MF_MT_YUV_MATRIX, yuv_video_matrix);

            UINT32 sample_size = 0;
            sample_size = MFGetAttributeUINT32(nativeType, MF_MT_SAMPLE_SIZE, sample_size);

            UINT32 curstride = 0;
            curstride = MFGetAttributeUINT32(nativeType, MF_MT_DEFAULT_STRIDE, curstride);

            GUID subtype = GUID_NULL;
            LONG tempStride = 0;
            nativeType->GetGUID(MF_MT_SUBTYPE, &subtype);
            MFGetStrideForBitmapInfoHeader(subtype.Data1, cwidth, &tempStride);
            
            WCHAR * pGuidValName;
            hr = GetGUIDName(nativeGuid, &pGuidValName);
            
            
            std::cout << count << ":  " << ConvertWCharToString(pGuidValName) << "\t" << cwidth << " x " << cheight << " : yuv_decode: " << yuv_video_matrix << " : sample size: " << sample_size << ": stride: " << curstride << ": tmpstride: " << tempStride << std::endl;

            if (nativeGuid == MFVideoFormat_NV12 && cwidth == requiredWidth && cheight == requiredheight) {
                // found native config, set it

                hr = IsMediaTypeSupported(nativeType);
                if (FAILED(hr)) {
                    std::cout << "Media type is not supported" << std::endl;
                    //return hr;
                }

                hr = sourceReader->SetCurrentMediaType(streamIndex, NULL, nativeType);
                if (FAILED(hr)) {
                    std::cout << "Failed to set Media type" << std::endl;
                    //return hr;
                }

                MFGetAttributeSize(nativeType, MF_MT_FRAME_SIZE, &width, &height);
                
                foundCorrectMediaType = true;
                break;
            }

            
            count++;
        }

    }

    if (!foundCorrectMediaType) {
        hr = E_FAIL;
        std::cout << "Cant find appropriate mediatype,exiting" << std::endl;
    }

    if (SUCCEEDED(hr)) {
        // Ask for the first sample.
        hr = sourceReader -> ReadSample((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL);
    }

    if (FAILED(hr)) {
        if (source) {
            source -> Shutdown();
        }
        //Close();
    }
    if (source) {
        source -> Release();
        source = NULL;
    }
    if (attributes) {
        attributes -> Release();
        attributes = NULL;
    }
    

    LeaveCriticalSection(&criticalSection);
    return hr;
}

Any thoughts?

I looked into the linker, at the moment im using

#pragma comment(lib, "Mfplat.lib")
#pragma comment(lib, "Mf.lib")
#pragma comment(lib, "Mfreadwrite.lib")
#pragma comment(lib, "mfuuid.lib")
#pragma comment(lib, "shlwapi.lib")

to include libraries, i would have expected a linker error if this was not appropriate in Release.


Solution

  • This is a bit stupid, and also to me unexpected behavior. I forgot InitializeCriticalSection(&criticalSection); In my class constructor.

    Apparently debug configuration handles this, release doesn't.