如何通过UVC支持硬件编码的H264

4

我正在使用Logitech C930e网络摄像头进行视频聊天,该应用程序是使用DirectShow创建的。到目前为止,我已能够使用YUY2或mJPEG格式的原始流。无论如何,我发现该网络摄像头支持通过UVC接口进行硬件H264编码。

目前,我正在使用标准方法获取可能的网络摄像头捕获引脚配置,但没有H264引脚。

void list_cameras {
    ICreateDevEnum *pDevEnum = nullptr;
    IEnumMoniker *pEnum = nullptr;

    // Create the System Device Enumerator.
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr,
                                  CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
                                  reinterpret_cast<void**>(&pDevEnum));
    if (SUCCEEDED(hr)) {
        // Create an enumerator for the video capture category.
        hr = pDevEnum->CreateClassEnumerator(
            CLSID_VideoInputDeviceCategory,
            &pEnum, 0);
        if (hr == S_FALSE) {
            return;
        }
    }

    IMoniker *pMoniker = nullptr; // IMoniker is the device
    int index = 0;

    // for each device
    while (pEnum->Next(1, &pMoniker, nullptr) == S_OK) {

        // bind camera to filter to be able to use it
        if (cam.device->BindToObject(nullptr, nullptr, IID_IBaseFilter, reinterpret_cast<void**>(&_pCapture)) != S_OK) {
            continue;
        }

        // fetch the configuration interface
        IAMStreamConfig *pConfig = nullptr;
        HRESULT hr = _capture->FindInterface(
            &PIN_CATEGORY_CAPTURE, // Preview pin.
            nullptr, // Any media type.
            _pCapture, // Pointer to the capture filter.
            IID_IAMStreamConfig, reinterpret_cast<void**>(&pConfig));

        if (FAILED(hr)) {
            continue;
        }

        // fetch possible configurations
        int iCount = 0, iSize = 0;
        if (pConfig->GetNumberOfCapabilities(&iCount, &iSize) != S_OK) {
            continue;
        }

        // store each configuration
        AM_MEDIA_TYPE *pmtConfig;
        for (int iFormat = 0; iFormat < iCount; iFormat++) {
            // get config
            VIDEO_STREAM_CONFIG_CAPS scc;
            if (pConfig->GetStreamCaps(iFormat, &pmtConfig, reinterpret_cast<BYTE*>(&scc)) != S_OK) {
                continue;
            }

            // copy config data
            VIDEOINFOHEADER *pVih = new VIDEOINFOHEADER(); // deleted afterwards
            *pVih = *reinterpret_cast<VIDEOINFOHEADER *>(pmtConfig->pbFormat);

            AM_MEDIA_TYPE mt;
            mt = *pmtConfig;
            mt.pbFormat = reinterpret_cast<BYTE *>(pVih);
            auto fcc = FOURCCMap(pVih->bmiHeader.biCompression);

            // wrap it
            CameraConfig config = { mt, pVih->bmiHeader.biWidth, pVih->bmiHeader.biHeight, 1000 / (static_cast<float>(pVih->AvgTimePerFrame) / 10000), fcc };

            // if resolution is bad (or unsupported), skip this configuration
            if (config.width == 0 || config.height == 0 ) // bad
                continue;

            cam.configurations.push_back(config);
        }
        _cameras.push_back(cam);

        pConfig->Release();
        _pCapture->Release();
    }

    pEnum->Release();
    pDevEnum->Release();
}

_cameras 是一个 Camera 类的向量,定义如下:

typedef struct {
    //! Pointer to DirectShow device.
    DSDevice device; 

    //! Camera name
    string name;

    //! List of supported configurations.
    vector<CameraConfig> configurations; // list of all available configurations

    //! Index of selected configuration.
    int selected;
} Camera;

_pCapture是指向创建的捕获过滤器的指针。 CameraConfig定义如下:

typedef struct {
    //! Media type.
    AM_MEDIA_TYPE _mediaType;

    //! Output width.
    int width;

    //! Outpus height.
    int height;

    //! Output framerate.
    float fps;

    //! Compression algoritm. YUY2 and mJPEG are supported for now.
    FOURCCMap compression;
} CameraConfig;

如何实现对UVC设备的支持?哪些硬件编码器参数可以被控制?

谢谢。


你正在通过DirectShow API使用相机。相机可以通过IAMStreamConfig等公认的方式(如YUY2,MJPG)或某些供应商特定的方式(SDK等),以特定于该型号的方式暴露出来。 - Roman R.
谢谢。是否有可靠的信息来源,可以了解哪些网络摄像头通过DirectShow API公开硬件编码的H264? - Dan Tumaykin
如果相机以“标准方式”暴露H.264捕获能力,则可以通过枚举其功能之一来查看它。其中一种方法是使用DirectShowCaptureCapabilities工具,通过IAMStreamConfig接口以编程方式显示所有内容。另一种方法是使用插入捕获过滤器的GraphStudioNext并浏览引脚媒体类型。无论哪种方式,您都应该看到H264AVC1子类型或biCompression值。 - Roman R.
顺便说一句,你的代码在处理IAMStreamConfig方面做得还不错,但你没有显示结果,我们对你的相机一无所知... - Roman R.
1
您对通过 IKsPropertySet::Get 方法显示 PIN_CATEGORY_CAPTURE 的引脚感兴趣。 - Roman R.
显示剩余4条评论
1个回答

2

在Windows 8.x下获取该流的唯一方法是不使用罗技驱动程序。这是一个兼容UVC 1.5的摄像头,操作系统会自动配置它。使用该驱动程序(来自微软),使用pin 1(而不是0)即可获得大量H264格式。

我认为,在Windows 7下,一些罗技驱动程序也提供了许多H264格式。

如果您在使用Windows 8.x并且已经安装了罗技驱动程序,则必须将其删除。这很困难。我通常通过编写类似于以下的结构来执行此操作(以管理员身份运行):

BOOL res;
res = SetupUninstallOEMInf(TEXT("oem131.inf"), SUOI_FORCEDELETE, nullptr );

如果你想删除哪些inf文件,这很简单:前往Windows\Inf文件夹并搜索Logitech。然后检查每个文件以确定确切的内容(你可能有一个鼠标或其他你想要保留的设备)。通常不止一个文件。


如果有人正在寻找查询和卸载驱动程序的解决方案,我开发了一个工具来完成这个任务。源代码可在GitHub上获得,详细信息请参见:http://mdinescu.com/software-development/30-driver-hunter-programatically-uninstall-drivers-in-windows - Mike Dinescu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接