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);
}
}