Code Monkey home page Code Monkey logo

Comments (2)

opendiff avatar opendiff commented on June 16, 2024

Here's sample code that initializes COM, enumerates video input devices, finds a specific device (4K60 Pro MK.2), prints its details, manages its properties (checks for HDR status and toggles HDR tonemapping), and finally releases resources before exiting.

#include <iostream>
#include <windows.h>
#include <dshow.h>

#pragma comment(lib, "strmiids.lib")
#include "DriverInterface.h"

template <class T>
void SafeRelease(T** ppT) {
    if (*ppT) {
        (*ppT)->Release();
        *ppT = NULL;
    }
}

HRESULT InitializeCOM() {
    return CoInitializeEx(NULL, COINIT_MULTITHREADED);
}

void UninitializeCOM() {
    CoUninitialize();
}

HRESULT EnumerateDevices(REFGUID category, IEnumMoniker** ppEnum)
{
    ICreateDevEnum* pDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));

    if (SUCCEEDED(hr))
    {
        
        hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
        if (hr == S_FALSE)
        {
            hr = VFW_E_NOT_FOUND;  
        }
        pDevEnum->Release();
    }
    return hr;
}

HRESULT EnumerateVideoDevices(IEnumMoniker** ppEnum) {
    return EnumerateDevices(CLSID_VideoInputDeviceCategory, ppEnum);
}

IMoniker* Find4K60ProMK2(IEnumMoniker* pEnum) {
    IMoniker* pMoniker = NULL;
    while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
        IPropertyBag* pPropBag = NULL;
        HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
        if (SUCCEEDED(hr)) {
            VARIANT varFriendlyName, varDevicePath;
            VariantInit(&varFriendlyName);
            VariantInit(&varDevicePath);

            
            hr = pPropBag->Read(L"FriendlyName", &varFriendlyName, 0);
            if (SUCCEEDED(hr)) {
                const wchar_t* expectedName = L"Game Capture 4K60 Pro MK.2";
                if (wcscmp(varFriendlyName.bstrVal, expectedName) == 0) {
                    
                    hr = pPropBag->Read(L"DevicePath", &varDevicePath, 0);
                    if (SUCCEEDED(hr)) {
                        const wchar_t* expectedPathPrefix = L"\\\\?\\pci#ven_12ab&dev_0710";
                        if (wcsncmp(varDevicePath.bstrVal, expectedPathPrefix, wcslen(expectedPathPrefix)) == 0) {
                            
                            VariantClear(&varFriendlyName);
                            VariantClear(&varDevicePath);
                            SafeRelease(&pPropBag);
                            return pMoniker; 
                        }
                    }
                }
            }
            
            VariantClear(&varFriendlyName);
            VariantClear(&varDevicePath);
            SafeRelease(&pPropBag);
        }
        SafeRelease(&pMoniker); 
    }
    return NULL; 
}

void PrintDeviceInfo(IMoniker* pMoniker) {
    if (pMoniker == NULL) {
        std::wcout << L"No moniker provided to PrintDeviceInfo." << std::endl;
        return;
    }

    IPropertyBag* pPropBag = NULL;
    HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
    if (SUCCEEDED(hr)) {
        VARIANT varFriendlyName, varDevicePath;
        VariantInit(&varFriendlyName);
        VariantInit(&varDevicePath);

        
        hr = pPropBag->Read(L"FriendlyName", &varFriendlyName, 0);
        if (SUCCEEDED(hr)) {
            std::wcout << L"Friendly Name: " << varFriendlyName.bstrVal << std::endl;
        }
        else {
            std::wcout << L"Could not read Friendly Name property." << std::endl;
        }

        
        hr = pPropBag->Read(L"DevicePath", &varDevicePath, 0);
        if (SUCCEEDED(hr)) {
            std::wcout << L"Device Path: " << varDevicePath.bstrVal << std::endl;
        }
        else {
            std::wcout << L"Could not read Device Path property." << std::endl;
        }

        VariantClear(&varFriendlyName);
        VariantClear(&varDevicePath);
        SafeRelease(&pPropBag);
    }
    else {
        std::wcout << L"Could not bind moniker to storage." << std::endl;
    }
}

EGAVDeviceProperties* CreateDeviceProperties(IMoniker* pMoniker) {
    IKsPropertySet* pKsPropertySet = nullptr;
    HRESULT hr = pMoniker->BindToObject(0, 0, IID_PPV_ARGS(&pKsPropertySet));
    if (SUCCEEDED(hr)) {
        
        auto deviceProperties = new EGAVDeviceProperties(pKsPropertySet, EGAVDeviceProperties::DeviceType::GC4K60ProMK2);
        pKsPropertySet->Release(); 
        return deviceProperties;
    }
    else {
        std::wcout << L"Failed to bind to IKsPropertySet interface." << std::endl;
        return nullptr;
    }
}

class DevicePropertiesManager {
private:
    EGAVDeviceProperties* m_pDeviceProperties;

public:
    
    DevicePropertiesManager(IMoniker* pMoniker) : m_pDeviceProperties(nullptr) {
        if (pMoniker) {
            m_pDeviceProperties = CreateDeviceProperties(pMoniker);
            if (!m_pDeviceProperties) {
                std::wcerr << L"Failed to create device properties." << std::endl;
            }
        }
    }

    ~DevicePropertiesManager() {
        delete m_pDeviceProperties;
    }

    DevicePropertiesManager(const DevicePropertiesManager&) = delete;
    DevicePropertiesManager& operator=(const DevicePropertiesManager&) = delete;

    
    bool IsVideoHDR() {
        if (m_pDeviceProperties) {
            bool isHDR = false;
            HRESULT hr = m_pDeviceProperties->IsVideoHDR(isHDR);
            if (SUCCEEDED(hr)) {
                return isHDR;
            }
            std::wcerr << L"Failed to get HDR status." << std::endl;
        }
        return false;
    }

    void SetHDRTonemappingEnabled(bool enabled) {
        if (m_pDeviceProperties) {
            HRESULT hr = m_pDeviceProperties->SetHDRTonemapping(enabled);
            if (FAILED(hr)) {
                std::wcerr << L"Failed to set HDR tonemapping." << std::endl;
            }
        }
    }

    HRESULT GetHDMIHDRStatusPacket(uint8_t* outBuffer, int inBufferSize) {
        if (m_pDeviceProperties) {
            
            return m_pDeviceProperties->GetHDMIHDRStatusPacket(outBuffer, inBufferSize);
        }
        else {
            std::wcerr << L"No device properties available to get HDMI HDR status packet." << std::endl;
            return E_FAIL; 
        }
    }
};

void MainProcess() {
    IEnumMoniker* pEnum = nullptr;
    HRESULT hr = EnumerateVideoDevices(&pEnum);
    if (SUCCEEDED(hr)) {
        IMoniker* pMoniker = Find4K60ProMK2(pEnum);
        if (pMoniker != nullptr) {
            PrintDeviceInfo(pMoniker);

            
            DevicePropertiesManager device(pMoniker);

            const int HDMI_PACKET_SIZE = 32; 
            uint8_t hdmiHDRStatusPacket[HDMI_PACKET_SIZE];
            HRESULT res = device.GetHDMIHDRStatusPacket(hdmiHDRStatusPacket, HDMI_PACKET_SIZE);
            std::cout << "GetHDMIHDRStatusPacket: ";
            if (SUCCEEDED(res)) {
                std::cout << "Successful" << std::endl;

                bool isHDR = device.IsVideoHDR();
                std::wcout << L"Is Video HDR? " << (isHDR ? L"Yes" : L"No") << std::endl;

                if (isHDR) {
                    
                    bool hdrToneMapping = false;
                    device.SetHDRTonemappingEnabled(hdrToneMapping);
                    std::wcout << L"HDR Tonemapping is now set to " << (hdrToneMapping ? L"enabled" : L"disabled") << std::endl;
                }

            }
            else {
                std::cout << "Error: Unknown (0x" << std::hex << res << ")" << std::endl;
            }


            pMoniker->Release(); 
        }
        else {
            std::wcout << L"Device not found." << std::endl;
        }
        SafeRelease(&pEnum);
    }
}

int main() {
    HRESULT hr = InitializeCOM();
    if (SUCCEEDED(hr)) {
        MainProcess();
        UninitializeCOM();
    }
    return 0;
}

from capture-device-support.

washtubs avatar washtubs commented on June 16, 2024

This is incredible thank you!

from capture-device-support.

Related Issues (4)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.