网络摄像头MJPG捕获流在Windows 10上不可用

时间:2016-08-05 09:51:19

标签: windows-10 webcam directshow video-capture ms-media-foundation

在Windows 10 build 10.1607.14393.10(又名周年纪念版)上,我无法再获取MJPG捕获流。曾经是MJPG和YUY2分辨率,现在我在DirectShow(内核流)和Media Foundation MJPG转换媒体类型中只获得YUY2到NV12方式,然后IBaseFilter源连接到任何东西。尝试使用不同相机的多个系统。什么想法可能是错的?

     640x480   @30   YUY2
     ...
     640x480   @30   MJPG <- gone
 ...
DirectShow:
    com_t<IAMStreamConfig> sc;
    if_failed_return_result(camera_output_pin->QueryInterface(&sc));
    int number_of_capabilities = 0;
    int capability_size = 0;
    if_failed_return(sc->GetNumberOfCapabilities(&number_of_capabilities, &capability_size), -1);
    for (int i = 0; i < number_of_capabilities && k < count; i++) {
        VIDEO_STREAM_CONFIG_CAPS scc;
        assert(sizeof(scc) == capability_size);
        AM_MEDIA_TYPE* mt = null;
        if_failed_return(sc->GetStreamCaps(i, &mt, (BYTE*)&scc), -1);
...

在MMF中:

    640x480   @30   YUY2
    ...
    640x480   @30   NV12 // camera reports MJPG 4cc in USBView and KsStudio

for (int i = 0; k < count; i++) {
    com_t<IMFMediaType> type;
    if (d->reader->GetNativeMediaType(VIDEO_STREAM, i, &type) != 0) {
        break;
    }
    GUID guid_major_type = {0};
    if_failed_return_result(type->GetMajorType(&guid_major_type));
    if (guid_major_type == MFMediaType_Video) {
        GUID guid_subtype = {0};
        if_failed_return_result(type->GetGUID(MF_MT_SUBTYPE, &guid_subtype));
        AM_MEDIA_TYPE* amMediaType = null;
        if_failed_return_result(type->GetRepresentation(FORMAT_MFVideoFormat, (void**)&amMediaType));
        assert(amMediaType->cbFormat == sizeof(MFVIDEOFORMAT));
        const MFVIDEOFORMAT* mi = (const MFVIDEOFORMAT*)amMediaType->pbFormat;

2 个答案:

答案 0 :(得分:3)

作为explained by Mike M from Microsoft

  

所以是的,MJPEG和H.264被解码/过滤是我们需要实现的一系列功能的结果,并且这种行为是我们的合作伙伴和Windows内部人员计划,设计,测试和实施的。今年1月底。我们与合作伙伴合作,确保他们的应用程序在整个变更过程中继续发挥作用,但我们在将这一变化传达给您们方面做得很差。我们把球丢在了前面,所以我想向你们道歉。

在Windows 10周年更新中,来自网络摄像头的MJPG视频由新的帮助服务&#34; Windows Camera Frame Server&#34;捕获,它自我介绍为&#34;允许多个客户端从相机访问视频帧设备。&#34 ;. Mike M也提到了同样的事情。

我一个人无法看到多个客户端共享摄像头,因为TopoEdit的第二个实例给了我典型的错误:开始播放时出错。由于缺少硬件资源,硬件MFT无法启动流式传输。

然而,MJPG和H264媒体类型确实被过滤掉了,因为平台更新现在声称有责任避免多个客户端同时访问同一个摄像头并且每个客户端自己进行解码而重复工作的情况。

  

Windows为您的应用程序解码MJPEG的主要原因之一是性能。随着Windows 10的周年纪念更新,现在可以让多个应用程序以前所未有的方式访问摄像机。对我们来说,启用并发摄像头访问非常重要,因此Windows Hello,Microsoft Hololens以及其他产品和功能可以可靠地假设摄像头在任何给定时间都可用,无论其他应用程序可能访问它。导致MJPEG解码的原因之一是因为我们想要防止多个应用程序同时解码相同的流,这将是一个重复的工作,因此不必要的性能损失。

显然这是&#34;改进&#34;让很多人感到意外。

<强>更新即可。通过创建如下定义的注册表值,检测到可以在系统范围内禁用使用新的帧服务器功能的行为。一旦Media Foundation API看到此值,它就会选择一个原始代码路径与&#34; hardware&#34; (KS代理)直接绕过Frame Server。

  • 键名:
    • HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows Media Foundation \ Platform(64位应用程序; 32位操作系统中的32位应用程序)
    • HKEY_LOCAL_MACHINE \ SOFTWARE \ WOW6432Node \ Microsoft \ Windows Media Foundation \ Platform(64位操作系统中的32位应用程序)
  • 值名称:&#34; EnableFrameServerMode&#34; REG_DWORD
  • 价值:0

答案 1 :(得分:1)

由于这是答案,让我先说明存在从黑客到昂贵的开发的几种解决方法

  1. (hack)从原来的Windows 10中取出旧的mfcore.dll,延迟与它的链接并强行加载你的本地副本 - 这是黑客不要在家尝试它不发货。
  2. 使用记录不足的ksproxy.ax或现代替换mfkproxy来实现自己的图层与摄像头对话。
  3. 将相机切换到WinUSB并使用libusb / libuvc(代码不是那么高性能而且在Windows上不成熟)并实现自己的相机界面
  4. 现在正确设计“帧服务器”:

    我们的zSpace系统设计中也有帧服务器,服务器解压缩图像,压缩摄像头(其中四个总计几乎每秒1Gpixel),blob检测信息和3D姿势三角测量结果到多个客户端(包括遥控器在内的应用程序)同一时间。使用共享内存和/或套接字的整个事情只有几百行直接C代码。我已经实现了它,它适用于Windows和Linux。

    微软“改进”的不足之处在于无视客户需求,我相信这很容易解决。

    为了论证,让我们假设相机流压缩格式(可能是MJPG / H.26x / HEVC /新的和更好的东西)。

    假设有几种可能的客户类别:

    1. 将原始压缩数据流式传输到远程主机网络的客户端(我们是否希望在那里进行转码?)。
    2. 将原始压缩数据存储在本地或远程永久存储(硬盘驱动器,ssd)中的客户端。 (我们想在那里进行转码吗?)
    3. 执行原始压缩数据流分析的客户端(从简单到复杂)但不需要像素?
    4. 实际操作压缩数据并将其传递到上游的客户端 - 记住可以裁剪,旋转例如JPEG没有完全解压缩。
    5. 需要HSI格式的未压缩数据的客户端。
    6. 需要RGB格式的未压缩数据且在解压缩期间应用了一些过滤器(例如,gamma,颜色配置文件)的客户端。
    7. 足够?今天他们都得到NV12(实际上,就U(Cb)和V(Cr)样本的半个带宽而言,实际上会造成更大的数据丢失。)

      现在,由于Microsoft正在实现帧服务器,他们必须以某种方式解压缩数据,甚至多种方式。为此,未压缩的数据必须落在存储器中并且可以(有条件地)保存在那里,以防某些客户端可以从中受益。最初的媒体图设计允许分离器和任何具有一点编码熟练度的人可以实现条件分割器,它只将数据推送到连接了客户端(接收器)的引脚。

      实际上,正确的实施应该考虑客户的需求(并且这些信息已经存在并且可以通过媒体类型协商和控制图形行为的属性的方式从所有客户端获得)。然后它应该仅在需要时密切注意cpu缓存局部性并通过适当的机制从适当的内存向适当的客户端提供所请求的数据,以应用解压缩器和其他过滤器。它将允许所有类型的优化在上述客户端及其后的混合的潜在排列中。

      如果微软在设计和实现满足这个简单(如果不是简单的话)要求的框架服务器方面需要帮助 - 它所要做的就是问 - 而不是破坏大量的应用程序和服务。

      我想知道微软是如何计划网络流Hollolens输入的?通过NV12?还是通过另一个黑客?

      “开发人员,开发人员,开发人员......”:(