How to support hardware encoded H264 though UVC
c++, directshow, h.264, video
Solution
The only way I was able to get that stream under Windows 8.x was by NOT USING LOGITECH DRIVERS. This is a UVC 1.5 compatible camera and it will be configured automatically by the OS. With that driver (from Microsoft), use pin 1 (not 0) and you will get a ton of H264 formats.
I think that under Windows 7, some drivers from Logitech give also a number of H264 formats.
In the case you are using Windows 8.x and you already have the Logitech driver installed you must remove that. And it is quite hard. I usually do it by writing constructs like this (run as admin):
BOOL res;
res = SetupUninstallOEMInf(TEXT("oem131.inf"), SUOI_FORCEDELETE, nullptr );
As to what inf you delete this is simple: go to Windows\Inf folder and search for Logitech. Then check each file o see what exactly is (you might have a mouse or something else you want to keep). Usually it is more than one.
Problem
I am using Logitech C930e webcam in a videochat application, created with DirectShow. So far I was able to use raw stream in YUY2 or mJPEG. Anyway, I have discovered that the webcam supports hardware H264 encoding though a UVC interface. Right now I using standart methods to fetch possible webcam capture pin configurations, but there is no H264 pin there. ``` 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` is a vector of Camera, defined as follows: ``` 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` is a pointer to the created capture filter. `CameraConfig` is defined as follows: ``` 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; ``` How do one implement a support for UVC devices? Which parameters of hardware encoder can be controlled? Thanks.