【问题标题】:Media Foundation Webcam live capture freezes in low light conditionMedia Foundation 网络摄像头实时捕捉在弱光条件下冻结
【发布时间】:2016-09-19 20:07:39
【问题描述】:

我们正在构建一个视频通信软件。我们正在使用 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 发生争执吗?

【问题讨论】:

    标签: c++ webcam video-capture ms-media-foundation


    【解决方案1】:

    您写道,网络摄像头“冻结” - 在低光照条件下拍摄图像时产生低帧率。其结果是网络摄像头的控制器在自动模式下需要更多时间来显示照片矩阵。它允许通过增加帧持续时间来提高图像质量。因此,它是硬件部分的特殊功能。可以将相机的这种行为从自动模式切换到参数的手动模式

    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 可能无效。媒体基础模型使用异步交互 - 在将请求发送到媒体源代码后,必须侦听来自媒体源的新帧或其他信息的响应。直接调用m_reader-&gt;ReadSample() 的方法是无效的——你面对它。方法m_reader-&gt;ReadSample() 可以有效地从视频文件中读取帧,而延迟可能非常低,但是对于网络摄像头,我可以建议使用拓扑 - 会话绑定,就像我的代码 Capturing Live-video from Web-camera on Windows 7 and Windows 8

    问候, 叶夫根尼·佩雷古达

    【讨论】:

    • 有趣,我必须彻底阅读您的代码示例,因为这种方法非常令人不安,但肯定很有趣。
    【解决方案2】:

    问题描述给人的印象是你做事有点混乱,导致卡顿不一定是媒体基金会或相机造成的。

    使用媒体源和源阅读器无疑是访问相机的正确方法,它提供了同步和异步捕获视频的有效方法。

    但是,您不完整的代码 sn-ps 表明您创建了一个媒体源,然后是源阅读器,然后您继续直接处理媒体源。好吧,你不应该这样做。创建源阅读器后,它将为您管理媒体源:您不需要Stop、Shutdown 调用。您调用该方法和其他方法可能会导致混淆,从而导致源阅读器行为不正确。

    也就是说,您要么处理媒体源,要么将其插入 Media Session 或 Source Reader 并使用这个更高级别的 API。

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

    【讨论】:

      猜你喜欢
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 2012-07-21
      • 2019-10-13
      • 1970-01-01
      • 2010-11-18
      相关资源
      最近更新 更多