【发布时间】:2020-04-08 11:40:11
【问题描述】:
我需要在屏幕上显示本地网络摄像头流, 水平翻转, 使屏幕看起来像一面镜子。 我有一个 DirectShow 图表可以完成所有这些, 除了镜像图像。 我尝试了几种方法来镜像图像, 但没有一个有效。
方法A:VideoControlFlag_FlipHorizontal
我尝试设置the VideoControlFlag_FlipHorizontal flag
在网络摄像头过滤器的输出引脚上,
像这样:
IAMVideoControl* pAMVidControl;
IPin* pWebcamOutputPin;
// ...
// Omitting error-handing for brevity
pAMVidControl->SetMode(pWebcamOutputPin, VideoControlFlag_FlipHorizontal);
但是,这没有任何效果。 事实上,网络摄像头过滤器声称没有此功能, 或任何其他功能:
long supportedModes;
hr = pAMVidControl->GetCaps(pWebcamOutputPin, &supportedModes);
// Prints 0, i.e. no capabilities
printf("Supported modes: %ld\n", supportedModes);
方法 B:SetVideoPosition
我尝试通过翻转传递给SetVideoPosition 的矩形来翻转图像。
(我在无窗口模式下使用增强型视频渲染器过滤器。)
有两个矩形:
源矩形和目标矩形。
我都试过了。
这是方法 B(i),
翻转源矩形:
MFVideoNormalizedRect srcRect;
srcRect.left = 1.0; // note flipped
srcRect.right = 0.0; // note flipped
srcRect.top = 0.0;
srcRect.bottom = 0.5;
return m_pVideoDisplay->SetVideoPosition(&srcRect, &destRect);
这不会显示任何内容。
它适用于其他配置,
但似乎不喜欢srcRect.left > srcRect.right。
这是方法 B(ii), 翻转目标矩形:
RECT destRect;
GetClientRect(hwnd, &destRect);
LONG left = destRect.left;
destRect.left = destRect.right;
destRect.right = left;
return m_pVideoDisplay->SetVideoPosition(NULL, &destRect);
这也不会显示任何内容。
它适用于其他配置,
但似乎不喜欢destRect.left > destRect.right。
方法 C:IMFVideoProcessorControl::SetMirror
IMFVideoProcessorControl::SetMirror(MF_VIDEO_PROCESSOR_MIRROR)
听起来像我想要的。
这个IMFVideoProcessorControl 接口由Video Processor MFT 实现。
不幸的是,这是一个媒体基础转换,
而且我看不到如何在 DirectShow 中使用它。
方法 D:视频调整器 DSP
Video Resizer DSP 是“可以充当 DMO 的 COM 对象”, 所以理论上我可以在 DirectShow 中使用它。 不幸的是,我没有使用 DMO 的经验, 无论如何, Video Resizer 的文档没有说明它是否支持翻转图像。
方法 E:IVMRMixerControl9::SetOutputRect
我发现
IVMRMixerControl9::SetOutputRect,
其中明确表示:
因为这个矩形存在于构图空间中, 没有“无效”矩形之类的东西。 例如,设置 left 大于 right 以在 x 方向上镜像视频。
但是,IVMRMixerControl9 似乎已被弃用,
我使用的是 EVR 而不是 VMR,
也没有关于如何获得IVMRMixerControl9 的文档。
方法 F:编写我自己的 DirectShow 过滤器
除非必须,否则我不愿意尝试这个。 这将是一项重大投资, 而且我不确定它的性能是否足够。
方法 G:从 Media Foundation 重新开始
媒体基金会可能会让我解决这个问题, 因为它提供了“媒体基础转换”。 但甚至不清楚 Media Foundation 是否符合我的所有其他要求。
我很惊讶我正在寻找如此激进的解决方案 对于看起来如此标准的转换。 还存在哪些其他方法? 在我尝试过的方法中有什么我忽略的吗? 如何在 DirectShow 中水平镜像视频?
【问题讨论】:
-
EVR 等效于选项 E 是
IMFVideoMixerControl::SetStreamOutputRect,也许这是第一个尝试的东西。接口本身可以通过IMFGetService获取(同here解释)。与 VMR-9 不同,在 EVR 中,混合器与渲染器本身是分离的,因此接口不能直接使用。选项 F 肯定行得通,G+C 也行,但这是一个备用计划。 -
@RomanR。谢谢!我忘了提到我实际上也试过那个!可悲的是,它也有同样的问题。这次文档实际上提到了它:“......边界矩形必须完全适合组合矩形,并且不能垂直或水平翻转。”现在,我正在考虑使用 MF 重新开始,因为我的应用程序足够小,以至于这种“升级”可能是比编写自己的过滤器更好的选择......
标签: c++ winapi video transform directshow