繁体   English   中英

Media Foundation网络摄像头实时捕获在弱光条件下冻结

[英]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或相机造成的。

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

但是,不完整的代码段表明您先创建媒体源,然后创建源阅读器,然后继续直接处理媒体源。 好吧,你不应该这样做。 创建源阅读器后,它将为您管理媒体源:您不需要StopShutdown调用。 您的调用方法和其他方法可能会引起混乱,从而导致错误的源阅读器行为。

也就是说,您可以处理媒体源,或者将其插入Media Session或Source Reader中并使用此更高级别的API。

还要注意,如果/当您遇到冻结时,您希望通过调试闯入并找到指示冻结位置的线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM