void MediaCaptureDevice::CurrentFormat::set()

in Sources/Media/Microsoft.Psi.Media_Interop.Windows.x64/MediaCaptureDevice.cpp [738:872]


void MediaCaptureDevice::CurrentFormat::set(CaptureFormat ^value)
{
    if (!fAttached)
    {
        throw gcnew InvalidOperationException();
    }

    if (value->nFrameRateDenominator == 0)
    {
        throw gcnew ArgumentOutOfRangeException("nFrameRateDenominator cannot not be 0"); // Check for invalid denominator
    }

    m_desiredRateNumerator = value->nFrameRateNumerator;

    if (value->subType->Guid == Guid::Empty)
    {
        throw gcnew ArgumentOutOfRangeException("subtype->Guid cannot be Guid::Empty"); // Require subtype
    }

    m_desiredRateDenominator = value->nFrameRateDenominator;

    array<Byte>^ rawGuid = value->subType->Guid.ToByteArray();
    pin_ptr<BYTE> pbData = &(rawGuid[0]);
    GUID subtype = *(_GUID *)pbData;


    HRESULT hr = S_OK;
    IMFMediaType *pMediaType = NULL;
    bool found = false;

    for (int nTypeIndex = 0; !found ;nTypeIndex++)
    {
        GUID nativeSubType;
        UINT32 resWidth = 0;
        UINT32 resHeight = 0;
        UINT32 numeratorRate = 0;
        UINT32 denominatorRate = 0;
        double desiredRate = ((double)value->nFrameRateNumerator) / value->nFrameRateDenominator;
        try
        {

            // Fetch the native media type and fill in set info
            hr = m_pSourceReader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, nTypeIndex, &pMediaType);
            MF_THROWHR(hr);

            hr = pMediaType->GetGUID(MF_MT_SUBTYPE, &nativeSubType);
            MF_THROWHR(hr);

            UINT64 res;
            hr = pMediaType->GetUINT64(MF_MT_FRAME_SIZE, &res);
            MF_THROWHR(hr);
            Unpack2UINT32AsUINT64(res, &resWidth, &resHeight);

            UINT64 rate;
            hr = pMediaType->GetUINT64(MF_MT_FRAME_RATE, &rate);
            MF_THROWHR(hr);
            Unpack2UINT32AsUINT64(rate, &numeratorRate, &denominatorRate);

            // Avoid divide by zero exception. We are being extra cautious here since MF shouldn't return a denominatorRate of 0.
            if (denominatorRate == 0)
            {
                continue;
            }

            double frameRate = ((double)numeratorRate) / denominatorRate;
            
            // Find a media match
            if (resWidth == (UINT32)value->nWidth &&
                resHeight == (UINT32)value->nHeight &&
				frameRate == desiredRate &&
				nativeSubType == subtype)
            {   
                hr = pMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
                MF_THROWHR(hr);

                hr = MFSetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, value->nWidth, value->nHeight);
                MF_THROWHR(hr);

                // Do not change the native frame rate of the webcam, since that causes letterboxing. RGB Camera will do the integer frame rate conversion.
                hr = MFSetAttributeRatio(pMediaType, MF_MT_FRAME_RATE, numeratorRate, denominatorRate);
                MF_THROWHR(hr);

				if (IsWindows8OrGreater())
				{
					hr = pMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24);
					MF_THROWHR(hr);
				}
				else
				{
					// We only support MJPG, YUY2  formats
					if (subtype == MFVideoFormat_MJPG || subtype == MFVideoFormat_YUY2)
					{
						// The WMV reader does not support mjpg as an input format. However, MF
						// will transcode if we set all of the other parameters up, but make the video type
						// YUY2.
				
						// Set the image frame format to YUY2
						hr = pMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2);
						MF_THROWHR(hr);
					}
					else
					{
						hr = MF_E_UNSUPPORTED_FORMAT;
						MF_THROWHR(hr);
					}
				}


                // Saves the callback from having to read this from the media format which can be expensive.
                m_callback->SetFormat(resWidth, resHeight);

                hr = m_pSourceReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pMediaType);
                MF_THROWHR(hr);

                found = true;
            }
            
            MF_RELEASE(pMediaType);
            if (found)
            {
                break;
            }
        }
        finally
        {
            MF_RELEASE(pMediaType);
        }
    }

    if (!found)
    {
        hr = MF_E_UNSUPPORTED_FORMAT;
        MF_THROWHR(hr);
    }
}