in src/color/mfcamerareader.cpp [292:492]
k4a_result_t CMFCameraReader::Start(const UINT32 width,
const UINT32 height,
const float fps,
const k4a_image_format_t imageFormat,
color_cb_stream_t *pCallback,
void *pCallbackContext)
{
RETURN_VALUE_IF_ARG(K4A_RESULT_FAILED, pCallback == nullptr);
RETURN_VALUE_IF_ARG(K4A_RESULT_FAILED, pCallbackContext == nullptr);
HRESULT hr = S_OK;
GUID guidDeviceSubType = GUID_NULL;
GUID guidOutputSubType = GUID_NULL;
switch (imageFormat)
{
case K4A_IMAGE_FORMAT_COLOR_NV12:
guidDeviceSubType = MFVideoFormat_NV12;
guidOutputSubType = MFVideoFormat_NV12;
break;
case K4A_IMAGE_FORMAT_COLOR_YUY2:
guidDeviceSubType = MFVideoFormat_YUY2;
guidOutputSubType = MFVideoFormat_YUY2;
break;
case K4A_IMAGE_FORMAT_COLOR_MJPG:
guidDeviceSubType = MFVideoFormat_MJPG;
guidOutputSubType = MFVideoFormat_MJPG;
break;
case K4A_IMAGE_FORMAT_COLOR_BGRA32:
if (width == 1280 && height == 720)
{
guidDeviceSubType = MFVideoFormat_NV12;
}
else
{
guidDeviceSubType = MFVideoFormat_MJPG;
}
guidOutputSubType = MFVideoFormat_ARGB32;
break;
default:
LOG_ERROR("Image Format %d is invalid", imageFormat);
return K4A_RESULT_FAILED;
}
if (!m_started)
{
bool typeFound = false;
DWORD typeIndex = 0;
ComPtr<IMFMediaType> spMediaType;
// Find target media type
while (!typeFound)
{
hr = m_spSourceReader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
typeIndex,
&spMediaType);
if (SUCCEEDED(hr))
{
UINT32 tempWidth = 0;
UINT32 tempHeight = 0;
UINT32 tempFpsNumerator = 0;
UINT32 tempFpsDenominator = 0;
GUID tempSubType = GUID_NULL;
if (FAILED(hr = MFGetAttributeSize(spMediaType.Get(), MF_MT_FRAME_SIZE, &tempWidth, &tempHeight)))
{
LOG_ERROR("Failed to get available frame size at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
if (FAILED(hr = MFGetAttributeRatio(spMediaType.Get(),
MF_MT_FRAME_RATE,
&tempFpsNumerator,
&tempFpsDenominator)))
{
LOG_ERROR("Failed to get available frame rate at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
if (FAILED(hr = spMediaType->GetGUID(MF_MT_SUBTYPE, &tempSubType)))
{
LOG_ERROR("Failed to get available color format at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
if (width == tempWidth && height == tempHeight &&
fps == ((float)tempFpsNumerator / (float)tempFpsDenominator) && guidDeviceSubType == tempSubType)
{
typeFound = true;
}
}
else if (hr == MF_E_NO_MORE_TYPES)
{
break;
}
else
{
LOG_ERROR("Failed to enumerate media type at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
typeIndex++;
}
if (typeFound)
{
ComPtr<IMFSourceReaderEx> spSourceReaderEx;
ComPtr<IMFMediaType> spOutputMediaType;
if (FAILED(hr = m_spSourceReader.As(&spSourceReaderEx)))
{
LOG_ERROR("Failed to get source reader extension at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
DWORD dwStreamFlags = 0;
if (FAILED(hr = spSourceReaderEx->SetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
spMediaType.Get(),
&dwStreamFlags)))
{
LOG_ERROR("Failed to set media type at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
if (guidDeviceSubType != guidOutputSubType)
{
// Create Output Media type
if (FAILED(hr = MFCreateMediaType(&spOutputMediaType)))
{
LOG_ERROR("Failed to create output media type at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
// Copy all items from device type to output type
if (FAILED(hr = spMediaType->CopyAllItems(spOutputMediaType.Get())))
{
LOG_ERROR("Failed to copy device type to output type at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
// Modify output media type
if (FAILED(hr = spOutputMediaType->SetGUID(MF_MT_SUBTYPE, guidOutputSubType)))
{
LOG_ERROR("Failed to set output subtype at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
}
else
{
spOutputMediaType = spMediaType;
}
if (FAILED(hr = m_spSourceReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
nullptr,
spOutputMediaType.Get())))
{
LOG_ERROR("Failed to set output media type at start: 0x%08x", hr);
return k4aResultFromHRESULT(hr);
}
}
else
{
LOG_ERROR("Can not find requested sensor mode", 0);
return K4A_RESULT_FAILED;
}
if (SUCCEEDED(hr = m_spSourceReader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE)))
{
auto lock = m_lock.LockExclusive();
m_width_pixels = width;
m_height_pixels = height;
m_image_format = imageFormat;
m_pCallback = pCallback;
m_pCallbackContext = pCallbackContext;
if (SUCCEEDED(hr = m_spSourceReader->ReadSample(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, nullptr, nullptr, nullptr, nullptr)))
{
m_started = true;
}
else
{
LOG_ERROR("Failed to request first sample at start: 0x%08x", hr);
}
}
else
{
LOG_ERROR("Failed to select stream at start: 0x%08x", hr);
}
}
else
{
LOG_WARNING("Start request in started state", 0);
}
if (FAILED(hr))
{
LOG_ERROR("Failing with HRESULT:%08X", hr);
}
return k4aResultFromHRESULT(hr);
}