2016-09-19 28 views
0

我们正在构建一个视频通信软件。我们正在使用媒体基金会获取实况流。我们使用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捕获,并正常工作。

有人在媒体基础上就同一问题挣扎吗?

回答

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

问候, 叶夫根尼·Pereguda

+0

有趣的是,我必须仔细阅读您的代码示例,因为这种方法相当令人不安,但确实很有趣。 –

0

的问题描述留下的印象是,你以一种有些混乱的方式来做事情,并且由此产生的冻结不一定是媒体基金会或相机造成的。

使用媒体源和源读取器当然是访问摄像机的正确方式,它提供了同步和异步捕获视频的有效方法。

但是,您的不完整代码片段显示您创建了一个媒体源,然后创建了源读取器,然后您继续直接处理媒体源。那么,你不应该这样做。一旦您创建了源读取器,它将为您管理媒体源:您不需要Stop,Shutdown调用。您的调用和其他方法可能会导致混淆,导致源读取器行为不正确。

也就是说,您要么处理媒体源,要么将其插入媒体会话或源读取器并使用此更高级别的API。

另请注意,如果/当您遇到冻结,您有兴趣进行调试并找到指示冻结位置的线程。