使用 EVR 直接通过媒体基础显示相机设备捕获的帧
Use EVR to display frames captured by camera device directly using Media Foundation
我正在尝试编写一个小应用程序,将相机设备捕获的视频帧直接显示在窗口上。我使用的是"源读取器"+"接收器写入器"体系结构而不是"媒体会话",因为我必须直接处理那些捕获的样本。我已经成功创建了源读取器,但是当我尝试创建EVR来显示帧时,遇到了一些问题...以下是我的代码:
HRESULT CCapture::CreatePreviewEVR(HWND hWindow)
{
// m_pPreviewSink, m_pPreviewStream, m_pPresentationClock, and m_pPresentationTimeSource
// are all defined as Class members
HRESULT hr = S_OK;
DWORD sinkCharacteristics = NULL;
IMFActivate *pPreviewSinkActive = NULL;
IMFClockStateSink *pClockStateSink = NULL;
hr = MFCreateVideoRendererActivate(hWindow, &pPreviewSinkActive);
if(SUCCEEDED(hr))
{
hr = pPreviewSinkActive->ActivateObject(IID_PPV_ARGS(&m_pPreviewSink));
}
if(SUCCEEDED(hr))
{
hr = m_pPreviewSink->GetCharacteristics(&sinkCharacteristics); // sinkCharacteristics is 0x18
}
if(SUCCEEDED(hr))
{
hr = m_pPreviewSink->GetStreamSinkByIndex(0, &m_pPreviewStream);
}
if(SUCCEEDED(hr))
{
hr = MFCreatePresentationClock(&m_pPresentationClock);
}
if(SUCCEEDED(hr))
{
hr = MFCreateSystemTimeSource(&m_pPresentationTimeSource);
}
if(SUCCEEDED(hr))
{
hr = m_pPresentationTimeSource->QueryInterface(__uuidof(IMFClockStateSink),(void**)&pClockStateSink);
}
if(SUCCEEDED(hr))
{
hr = m_pPresentationClock->SetTimeSource(m_pPresentationTimeSource);
}
if(SUCCEEDED(hr))
{
hr = m_pPresentationClock->AddClockStateSink(pClockStateSink);
}
if(SUCCEEDED(hr))
{
hr = m_pPreviewSink->SetPresentationClock(m_pPresentationClock);
}
return hr;
}
HRESULT CCapture::ConfigurePreviewEVR()
{
// This function is implemented trying to do EVR Media Type Negotiation
DWORD mediaTypeCount = 0;
HRESULT hr =S_OK;
IMFMediaType *pSourceReaderType = NULL;
IMFMediaType *pSourceReaderTypeValid = NULL;
IMFMediaType *pPreviewSinkMediaType = NULL;
IMFMediaTypeHandler *pPreviewSinkMediaTypeHandler = NULL;
hr = m_pReader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pSourceReaderType);
if(SUCCEEDED(hr))
{
hr = MFCreateMediaType(&pPreviewSinkMediaType);
}
if(SUCCEEDED(hr))
{
hr = pPreviewSinkMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
}
if(SUCCEEDED(hr))
{
hr = pPreviewSinkMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
}
if(SUCCEEDED(hr))
{
hr = pPreviewSinkMediaType->SetUINT32(MF_MT_AVG_BITRATE, 14000000);
}
if(SUCCEEDED(hr))
{
hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_FRAME_SIZE);
}
if(SUCCEEDED(hr))
{
hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_FRAME_RATE);
}
if(SUCCEEDED(hr))
{
hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_PIXEL_ASPECT_RATIO);
}
if(SUCCEEDED(hr))
{
hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_INTERLACE_MODE);
}
if(SUCCEEDED(hr))
{
hr = m_pPreviewStream->GetMediaTypeHandler(&pPreviewSinkMediaTypeHandler);
}
if(SUCCEEDED(hr))
{
hr = pPreviewSinkMediaTypeHandler->GetMediaTypeCount(&mediaTypeCount); // derived mediaTypeCount is 0
}
if(SUCCEEDED(hr))
{
hr = pPreviewSinkMediaTypeHandler->IsMediaTypeSupported(pSourceReaderType, &pSourceReaderTypeValid); // Failed to get supported Media Type
}
if(SUCCEEDED(hr))
{
hr = pPreviewSinkMediaTypeHandler->SetCurrentMediaType(pSourceReaderTypeValid); // This function still fails if I use pSourceReaderType directly
}
if(SUCCEEDED(hr))
{
SafeRelease(&pSourceReaderType);
SafeRelease(&pPreviewSinkMediaType);
SafeRelease(&pPreviewSinkMediaTypeHandler);
}
return hr;
}
函数"CopyAttribute"来自MFCaptureToFile示例代码,它可以正常工作。由于变量"sinkFeatures"给出了0x18,似乎我应该能够将我希望使用的媒体类型的新流添加到媒体接收器;但是我尝试了AddStreamSink函数,但它直接返回了错误。"CCapture"类继承自IMFSourceReaderCallBack,如果我的理解是正确的,我应该在OnReadSample回调函数中使用m_pPreviewStream->ProcessSample(pSample)。如果有人能在这方面提供帮助,非常感谢!此致敬意
这
似乎很混乱。
当您希望 EVR 显示来自多个源的帧时,您必须使用 AddStreamSink。
阅读您的帖子时,您希望仅显示来自相机的帧(一个来源)。
因此,您不需要使用 AddStreamSink。
而且,您会收到来自 AddStreamSink 的错误,因为在将流添加到 EVR 时要使用的媒体类型存在一些限制(这取决于您的 GPU 特征)。
相关文章:
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 字符串-C++后显示的随机字符
- Qt QML相机在部署后显示白屏
- 在直接显示中查询相机控件
- 如何使用win IoT在Raspberry Pi上的相机中显示视频流以及一些图像处理
- 如何显示视频捕获过滤器对话框(亮度,曝光等相机设置)
- 使用树莓派相机和打开简历显示视频时出错
- 使用Qt显示相机图像会出现HIGHGUI错误:V4L/V4L2:VIDIOC_S_CROP
- 可能存在SDL_Net问题和使用 openCV 显示内存中的 YUV 相机帧
- 在来自相机的视频上显示一个矩形
- 使用直接显示控制相机,并使用打开的CV捕获图像
- 使用 EVR 直接通过媒体基础显示相机设备捕获的帧
- 访问Ximea相机并使用OpenCV设置预定义的分辨率时,由于相机默认分辨率的大小为Mat,因此显示混乱的输出
- 如何在媒体基金会中控制相机捕获显示
- 使用C++与3000Hz的线阵扫描相机接口,并处理/显示数据
- gstreamer 管道代码,用于通过来自相机的实时流式传输而不是图像显示文本
- 最大的相机抓取和显示性能
- 使用相机旋转使四边形始终显示在相机前面(c++/opengl)
- OpenCV 不会显示分辨率大于 640x480 的相机源