[英]Media Foundation Webcam live capture freezes in low light condition
我们正在构建视频通信软件。 我们正在使用Media Foundation获得直播。 我们使用IMFSourceReadder执行捕获。
调用顺序如下:
hr = pAttributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, m_pwszSymbolicLink);
hr = MFCreateDeviceSourceActivate(pAttributes, &avdevice);
hr = avdevice->ActivateObject(__uuidof(IMFMediaSource), (void**) &m_mediaSource);
hr = m_mediaSource->CreatePresentationDescriptor(&pPD);
hr = pPD->GetStreamDescriptorByIndex(m_streamIdx, &fSelected, &pSD);
hr =
// we select the best native MediaType enumerating the source reader
pHandler->SetCurrentMediaType(m_bestNativeType);
hr = pAttributes->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, FALSE);
hr = pAttributes->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE);
hr = MFCreateSourceReaderFromMediaSource(m_mediaSource, pAttributes, &m_reader);
然后,我们开始使用一个单独的线程同步读取帧
m_reader->ReadSample()
当我们需要停止设备或重新配置设备时,我们将停止线程(通过设置标志并退出线程)。 我们称以下
hr = m_mediaSource->Stop();
m_mediaSource->Shutdown();
SafeRelease(&m_mediaSource);
SafeRelease(&m_reader);
该软件可以拨打电话。 在那里,它以VGA格式捕获网络摄像头视频并将其显示在屏幕上。 在通话中,它将根据协商的通话质量选择最佳的捕获格式,然后重新开始捕获。
我们遇到的问题如下:有些相机有时在光线不足的情况下会冻结(低fps输出)。 它可以在通话开始时或通话期间立即发生。
冻结时,可能会发生两种情况之一(不确定哪一种)
m_reader-> ReadSample()重复失败,错误代码为MF_E_OPERATION_CANCELLED
m_reader-> ReadSample()返回通常每秒产生80帧以上,并产生相同的冻结图像。
挂断电话后,设备将重新配置为VGA捕获,并且工作正常。
是否有人在同一问题上与Media Foundation斗争?
您写了网络摄像机“ freez”-在低光照条件下捕获图像时产生低帧频。 网络摄像机控制器在自动模式下曝光照片矩阵所花费的时间更多。 通过增加帧持续时间,可以提高图像质量。 因此,它是硬件部分的特色。 可以将摄像机的这种行为从自动模式切换到参数的手动模式
Code::Result VideoCaptureDevice::setParametrs(CamParametrs parametrs){
ResultCode::Result result = ResultCode::VIDEOCAPTUREDEVICE_SETPARAMETRS_ERROR;
if(pLocalSource)
{
unsigned int shift = sizeof(Parametr);
Parametr *pParametr = (Parametr *)(&settings);
Parametr *pPrevParametr = (Parametr *)(&prevParametrs);
CComPtrCustom<IAMVideoProcAmp> pProcAmp;
HRESULT hr = pLocalSource->QueryInterface(IID_PPV_ARGS(&pProcAmp));
if (SUCCEEDED(hr))
{
for(unsigned int i = 0; i < 10; i++)
{
if(pPrevParametr[i].CurrentValue != pParametr[i].CurrentValue || pPrevParametr[i].Flag != pParametr[i].Flag)
hr = pProcAmp->Set(VideoProcAmp_Brightness + i, pParametr[i].CurrentValue, pParametr[i].Flag);
}
}
else
{
result = ResultCode::VIDEOCAPTUREDEVICE_SETPARAMETRS_SETVIDEOPROCESSOR_ERROR;
goto finish;
}
CComPtrCustom<IAMCameraControl> pProcControl;
hr = pLocalSource->QueryInterface(IID_PPV_ARGS(&pProcControl));
if (SUCCEEDED(hr))
{
for(unsigned int i = 0; i < 7; i++)
{
if(pPrevParametr[10 + i].CurrentValue != pParametr[10 + i].CurrentValue || pPrevParametr[10 + i].Flag != pParametr[10 + i].Flag)
hr = pProcControl->Set(CameraControl_Pan+i, pParametr[10 + i].CurrentValue, pParametr[10 + i].Flag);
}
}
else
{
result = ResultCode::VIDEOCAPTUREDEVICE_SETPARAMETRS_SETVIDEOCONTROL_ERROR;
goto finish;
}
result = ResultCode::OK;
prevParametrs = parametrs.settings;
}finish:
if(result != ResultCode::OK)
DebugPrintOut::getInstance().printOut(L"VIDEO CAPTURE DEVICE: Parametrs of video device cannot be set!!!\n");
return result;
}
哪里:
struct Parametr
{
long CurrentValue;
long Min;
long Max;
long Step;
long Default;
long Flag;
Parametr();
};
struct CamParametrs
{
Parametr Brightness;
Parametr Contrast;
Parametr Hue;
Parametr Saturation;
Parametr Sharpness;
Parametr Gamma;
Parametr ColorEnable;
Parametr WhiteBalance;
Parametr BacklightCompensation;
Parametr Gain;
Parametr Pan;
Parametr Tilt;
Parametr Roll;
Parametr Zoom;
Parametr Exposure;
Parametr Iris;
Parametr Focus;
};
您可以在网站上找到更多代码:
在Windows 7和Windows 8上从网络摄像机捕获实时视频
但是,使用IMFSourceReader
可能无效。 Media Foundation模型使用异步交互-将请求发送到媒体源代码后,必须侦听来自媒体源的具有新框架或其他信息的响应。 直接调用m_reader->ReadSample()
方法无效-您面对了它。 方法m_reader->ReadSample()
可以有效地从视频文件中读取帧,而延迟可以非常低,但是对于网络摄像机,我建议使用拓扑-会话绑定,就像我的代码从Windows上的网络摄像机捕获实时视频一样7和Windows 8
问候,Evgeny Pereguda
问题描述给人的印象是您以某种混乱的方式进行操作,并且由此导致的死机不一定是Media Foundation或相机造成的。
媒体源和源阅读器的使用无疑是访问摄像机的正确方法,它提供了同步和异步捕获视频的有效方法。
但是,不完整的代码段表明您先创建媒体源,然后创建源阅读器,然后继续直接处理媒体源。 好吧,你不应该这样做。 创建源阅读器后,它将为您管理媒体源:您不需要Stop
, Shutdown
调用。 您的调用方法和其他方法可能会引起混乱,从而导致错误的源阅读器行为。
也就是说,您可以处理媒体源,或者将其插入Media Session或Source Reader中并使用此更高级别的API。
还要注意,如果/当您遇到冻结时,您希望通过调试闯入并找到指示冻结位置的线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.