我们正在构建视频通信软件。我们正在使用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);
然后我们开始使用
在一个单独的线程中读取SYNCHRONOUSLY帧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捕获并正常工作。
是否有人在同一问题上与媒体基金会斗争?
答案 0 :(得分:0)
你写了那个网络摄像头" 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;
};
您可以在网站上找到更多代码:
Capturing Live-video from Web-camera on Windows 7 and Windows 8
然而,使用IMFSourceReader
可能无效。 Media Foundation模型使用异步交互 - 在将请求发送到媒体源代码后,必须使用新帧或其他信息从媒体源收听响应。直接调用m_reader->ReadSample()
的方法无效 - 您面对它。方法m_reader->ReadSample()
可以有效地从视频文件中读取帧,而延迟可能非常低,但对于网络摄像头,我可以建议使用拓扑 - 会话绑定,就像在我的代码中Capturing Live-video from Web-camera on Windows 7 and Windows 8
此致 Evgeny Pereguda
答案 1 :(得分:0)
问题描述给人的印象是你以一种有点混乱的方式做事,结果冻结不一定是由Media Foundation或相机引起的。
使用媒体源和源阅读器无疑是访问摄像机的正确方法,它提供了同步和异步捕获视频的有效方式。
但是,您的不完整代码段显示您创建了媒体源,然后是源阅读器,然后您将继续直接处理媒体源。好吧,你不应该这样做。创建源阅读器后,它将为您管理媒体源:您不需要Stop
,Shutdown
来电。您调用该方法和其他方法可能会导致混淆,导致源阅读器行为不正确。
即,您要么处理媒体源,要么将其插入媒体会话或源阅读器并使用此更高级别的API。
另请注意,如果/当您遇到冻结时,您有兴趣使用调试并找到指示冻结位置的线程。