如何为Windows 10笔记本电脑上的网络摄像头捕获设置IMFSourceReader的帧速率

问题描述

我已经看到了其他问题,但是不知何故对我不起作用。 环境:Windows 10 MediaFoundation / SourceReader处于异步模式。LogitechC922网络摄像头1080p专业版

问题:

  1. 我正在尝试使用SourceReader在异步模式下使用Media Foundation阅读网络摄像头。我接到::OnReadSample()的呼叫频率为60-65毫秒,而不是30fps的33.33毫秒。

  2. 验证人

hr = m_pReader->GetCurrentMediaType(
            (DWORD)MF_SOURCE_READER_FirsT_VIDEO_STREAM,&pType
            );

,并且MF_MT_FRAME_RATE为30 x 1的pType的打印属性MINMAX RANGE均为30 x 1。

  1. ::OnReadSample()回调中得到验证,并且Mediatype相同。没有为MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED位设置流标志。因此,currentmediatype在内部没有改变。
hr = m_pReader->GetCurrentMediaType(
                (DWORD)MF_SOURCE_READER_FirsT_VIDEO_STREAM,&pt
                );
  1. 即使使用 https://docs.microsoft.com/en-us/windows/win32/medfound/how-to-set-the-video-capture-frame-rate上一页的确切功能,但仍每64毫秒左右调用一次。 以下是正在使用的pType的快照。
MF_MT_FRAME_SIZE    640 x 480
MF_MT_AVG_BITRATE   147456000
MF_MT_YUV_MATRIX    2
MF_MT_MAJOR_TYPE    MFMediaType_Video
MF_MT_VIDEO_LIGHTING    3
MF_MT_DEFAULT_STRIDE    1280
MF_MT_VIDEO_CHROMA_SITING   6
MF_MT_AM_FORMAT_TYPE    {F72A76A0-EB0A-11D0-ACE4-0000C0CC16BA}
MF_MT_FIXED_SIZE_SAMPLES    1
MF_MT_VIDEO_NOMINAL_RANGE   2
MF_MT_FRAME_RATE    30 x 1
MF_MT_PIXEL_ASPECT_RATIO    1 x 1
MF_MT_ALL_SAMPLES_INDEPENDENT   1
MF_MT_FRAME_RATE_RANGE_MIN  30 x 1
MF_MT_SAMPLE_SIZE   614400
MF_MT_VIDEO_PRIMARIES   2
MF_MT_INTERLACE_MODE    2
MF_MT_FRAME_RATE_RANGE_MAX  30 x 1
MF_MT_SUBTYPE   MFVideoFormat_YUY2

请提出在这种情况下可能缺少的内容。我得到的是15fps,而不是30fps。我已经列举了设备的媒体类型,它支持30fps。

谢谢。

解决方法

可能是因为您是在IMFSourceReader而不是IMFMediaSource的处理程序上设置调整后的媒体类型。

完整的example的摘录如下所示。请注意,定制的媒体类型是在pSourceMediaTypeHandler而非pVideoReader上设置的。有关变量声明等,请参见示例源代码。

// ----- Set up webcam video source. -----

CHECK_HR(GetVideoSourceFromDevice(WEBCAM_DEVICE_INDEX,&pVideoSource,&pVideoReader),"Failed to get webcam video source.");

CHECK_HR(pVideoReader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,TRUE),"Failed to set the first video stream on the source reader.");

CHECK_HR(pVideoSource->CreatePresentationDescriptor(&pSourcePresentationDescriptor),"Failed to create the presentation descriptor from the media source.");

CHECK_HR(pSourcePresentationDescriptor->GetStreamDescriptorByIndex(0,&fSelected,&pSourceStreamDescriptor),"Failed to get source stream descriptor from presentation descriptor.");

CHECK_HR(pSourceStreamDescriptor->GetMediaTypeHandler(&pSourceMediaTypeHandler),"Failed to get source media type handler.");

DWORD srcMediaTypeCount = 0;
CHECK_HR(pSourceMediaTypeHandler->GetMediaTypeCount(&srcMediaTypeCount),"Failed to get source media type count.");

// ----- Attempt to set the desired media type on the webcam source. -----

CHECK_HR(MFCreateMediaType(&pWebcamSourceType),"Failed to create webcam output media type.");

CHECK_HR(FindMatchingVideoType(pSourceMediaTypeHandler,WEBCAM_PIXEL_FORMAT,VIDEO_WIDTH,VIDEO_HEIGHT,VIDEO_FRAME_RATE,pWebcamSourceType),"No matching webcam media type was found.");

// This check is not necessary if the media type was from the list of supported types.
// It is useful if the media type is constructed manually. It is left here for demonstration purposes. 
CHECK_HR(pSourceMediaTypeHandler->IsMediaTypeSupported(pWebcamSourceType,&pWebCamMatchingType),"Webcam does not support requested options.");

if (pWebCamMatchingType != NULL) {
// If IsMediaTypeSupported supplied us with the closest matching media type use that.
CHECK_HR(pSourceMediaTypeHandler->SetCurrentMediaType(pWebCamMatchingType),"Failed to set media type on source.");
}
else {
// If IsMediaTypeSupported did not supply us a new type the typ checked must have been good enough use that.
CHECK_HR(pSourceMediaTypeHandler->SetCurrentMediaType(pWebcamSourceType),"Failed to set media type on source.");
}

CHECK_HR(pSourceMediaTypeHandler->GetCurrentMediaType(&pVideoSourceOutputType),"Error retrieving current media type from first video stream.");

std::cout << "Webcam media type:" << std::endl;
std::cout << GetMediaTypeDescription(pVideoSourceOutputType) << std::endl << std::endl;

我使用该示例来确认我能够将Logitech C920的帧速率设置为5fps,并在源阅读器循环中获得正确的采样率。

Attempting to convert sample,sample duration 2000000,sample time 863168227222,evr timestamp 0.
Attempting to convert sample,sample time 863170145312,evr timestamp 2000000.
Attempting to convert sample,sample time 863172227244,evr timestamp 4000000.
Attempting to convert sample,sample time 863174144901,evr timestamp 6000000.
Attempting to convert sample,sample time 863176225938,evr timestamp 8000000.
Attempting to convert sample,sample time 863178147388,evr timestamp 10000000.
Attempting to convert sample,sample time 863180225543,evr timestamp 12000000.