인코더 코드 예제

다음 코드 예제는 AVSHwS(AVStream 시뮬레이션 하드웨어 샘플 드라이버)를 기반으로 합니다. 다음을 보여 줍니다.

  • 인코더의 지원되는 비트 전송률을 지정하는 방법

  • 인코더에서 지원하는 비트 속도 인코딩 모드를 지정하는 방법

  • 인코더 디바이스의 디바이스 매개 변수\기능 레지스트리 키에서 런타임에 메타데이터 값을 지정하는 방법

지원되는 비트 전송률 구현

다음 코드 조각은 ENCAPIPARAM_BITRATE 속성에 대한 지원을 구현하는 방법을 보여 줍니다. KSPROPERTY_STEPPING_LONG 구조를 사용하여 400-bps 하한 및 4,000,000-bps 상한이 있는 초당 400비트(bps)의 단계별 세분성을 지정합니다.

const KSPROPERTY_STEPPING_LONG BitRateRanges [] = {
    {
        400,
        0,
        400,
        4000000
    }
};

GraphEdit와 같은 도구에서 필터를 마우스 오른쪽 단추로 클릭하여 인코더 필터의 속성 페이지에 액세스하는 경우 이러한 값이 사용되는 비트 비율 슬라이더 막대가 표시됩니다.

다음으로, 인코더 필터의 instance 만들 때 인코더 필터의 기본 인코딩 비트 속도를 지정합니다. 사용되는 데이터 형식은 ENCAPIPARAM_BITRATE 속성에 필요한 속성 값 형식에 해당하는 ULONG입니다. 이 값은 인코더의 속성 페이지에 표시되는 기본 인코딩 "비트 속도"입니다.

const ULONG BitRateValues [] = {
    1000000
};

법적 범위 목록과 ENCAPIPARAM_BITRATE 속성의 기본값을 지정합니다.

 const KSPROPERTY_MEMBERSLIST BitRateMembersList [] = {
    {
        {
            KSPROPERTY_MEMBER_STEPPEDRANGES,
            sizeof (BitRateRanges),
            SIZEOF_ARRAY (BitRateRanges),
            0
        },
        BitRateRanges
    },
    {
        {
            KSPROPERTY_MEMBER_VALUES,
            sizeof (BitRateValues),
            SIZEOF_ARRAY (BitRateValues),
            KSPROPERTY_MEMBER_FLAG_DEFAULT
        },
        BitRateValues
    }
};
 const KSPROPERTY_VALUES BitRateValuesSet = {
    {
        STATICGUIDOF (KSPROPTYPESETID_General),
        VT_UI4,
        0
    },
    SIZEOF_ARRAY (BitRateMembersList),
    BitRateMembersList
};

ENCAPIPARAM_BITRATE 속성 집합에 대해 정의된 단일 속성을 지정합니다.

DEFINE_KSPROPERTY_TABLE(ENCAPI_BitRate) {
    DEFINE_KSPROPERTY_ITEM (
        0,
        GetBitRateHandler, //Get-property handler supported
        sizeof (KSPROPERTY),
        sizeof (ULONG),
        SetBitRateHandler, //Set-property handler supported
        &BitRateValuesSet,
        0,
        NULL,
        NULL,
        sizeof (ULONG)
        )
};

참고

get-property 처리기는 인코딩 비트 속도를 반환하며 Set-property 처리기는 들어오는 전달된 값이 유효한지 테스트해야 합니다.

지원되는 인코딩 비트 전송률 모드 구현

다음 코드 조각은 ENCAPIPARAM_BITRATE_MODE 속성에 대한 지원을 구현하는 방법을 보여 줍니다.

인코더에서 지원하는 인코딩 모드를 정의합니다.

 const VIDEOENCODER_BITRATE_MODE BitRateModeValues [] = {
    ConstantBitRate,
    VariableBitRateAverage
};

기본 인코딩 비트 전송률 모드를 평균 변수 비트 전송률로 지정합니다.

const VIDEOENCODER_BITRATE_MODE BitRateModeDefaultValues [] = {
    VariableBitRateAverage
};

ENCAPIPARAM_BITRATE_MODE 속성에 대한 법적 범위 및 기본값 목록을 지정합니다.

const KSPROPERTY_MEMBERSLIST BitRateModeMembersList [] = {
    {
        {
            KSPROPERTY_MEMBER_VALUES,
            sizeof (BitRateModeValues),
            SIZEOF_ARRAY (BitRateModeValues),
            0
        },
        BitRateModeValues
    },
    {
        {
            KSPROPERTY_MEMBER_VALUES,
            sizeof (BitRateModeDefaultValues),
            SIZEOF_ARRAY (BitRateModeDefaultValues),
            KSPROPERTY_MEMBER_FLAG_DEFAULT
        },
        BitRateModeDefaultValues
    }
};

const KSPROPERTY_VALUES BitRateModeValuesSet = {
    {
        STATICGUIDOF (KSPROPTYPESETID_General),
        VT_I4,
        0
    },
    SIZEOF_ARRAY (BitRateModeMembersList),
    BitRateModeMembersList
};

ENCAPIPARAM_BITRATE_MODE 속성 집합에 대해 정의된 단일 속성을 지정합니다.

DEFINE_KSPROPERTY_TABLE(ENCAPI_BitRateMode) {
    DEFINE_KSPROPERTY_ITEM (
        0,
        GetBitRateModeHandler, //Get-property handler supported
        sizeof (KSPROPERTY),
        sizeof (VIDEOENCODER_BITRATE_MODE),
        SetBitRateModeHandler, //Set-property handler supported
        &BitRateModeValuesSet,
        0,
        NULL,
        NULL,
        sizeof (VIDEOENCODER_BITRATE_MODE)
        )
};

참고

get-property 처리기는 인코딩 비트 전송률 모드를 반환해야 하며 Set-property 처리기는 들어오는 전달된 값이 유효한지 테스트해야 합니다.

그런 다음 속성 집합은 KSFILTER_DESCRIPTOR 구조체의 자동화 테이블로 지정됩니다.

DEFINE_KSPROPERTY_SET_TABLE(PropertyTable) {
    DEFINE_KSPROPERTY_SET(
        &ENCAPIPARAM_BITRATE_MODE,
        SIZEOF_ARRAY (ENCAPI_BitRateMode),
        ENCAPI_BitRateMode,
        0,
        NULL
        ),
    DEFINE_KSPROPERTY_SET(
        &ENCAPIPARAM_BITRATE,
        SIZEOF_ARRAY (ENCAPI_BitRate),
        ENCAPI_BitRate,
        0,
        NULL
        )
};

DEFINE_KSAUTOMATION_TABLE(FilterTestTable) {
    DEFINE_KSAUTOMATION_PROPERTIES(PropertyTable),
    DEFINE_KSAUTOMATION_METHODS_NULL,
    DEFINE_KSAUTOMATION_EVENTS_NULL
};

const
KSFILTER_DESCRIPTOR
FilterDescriptor = {
    ...,
    &FilterTestTable, // Automation Table
    ...,
    ...
};

레지스트리에서 인코더의 기능 지정

다음 코드 샘플에서는 디바이스 매개 변수 레지스트리 키 아래에 Capabilities 레지스트리 키를 만드는 방법과 기능 키 아래에 하위 키와 값을 만들고 지정하는 방법을 보여 줍니다. 드라이버가 초기화되면 이 코드를 실행합니다.

참고

다음 코드에서는 물리적 디바이스당 단일 하드웨어 인코더가 있다고 가정합니다. 하드웨어에 둘 이상의 인코더가 포함된 경우 IoGetDeviceInterfaces 함수 호출에서 반환된 목록을 반복하고 각 인코더에 대한 기능을 등록해야 합니다.

/**************************************************************************
CreateDwordValueInCapabilityRegistry()

IN Pdo: PhysicalDeviceObject
IN categoryGUID: Category GUID eg KSCATEGORY_CAPTURE

1. Get Symbolic name for interface
2. Open registry key for storing information about a
   particular device interface instance
3. Create Capabilities key under "Device Parameters" key
4. Create a DWORD value "TestCapValueDWORD" under Capabilities

Must be running at IRQL = PASSIVE_LEVEL in the context of a system thread
**************************************************************************/
NTSTATUS CreateDwordValueInCapabilityRegistry(IN PDEVICE_OBJECT pdo, IN GUID categoryGUID)

{

    // 1. Get Symbolic name for interface
    // pSymbolicNameList can contain multiple strings if pdo is NULL.
    // Driver should parse this list of string to get
    // the one corresponding to current device interface instance.
    PWSTR  pSymbolicNameList = NULL;

    NTSTATUS ntStatus = IoGetDeviceInterfaces(
        &categoryGUID,
        pdo,
        DEVICE_INTERFACE_INCLUDE_NONACTIVE,
        &pSymbolicNameList);
    if (NT_SUCCESS(ntStatus) && (NULL != pSymbolicNameList))
    {
        HANDLE hDeviceParametersKey = NULL;
        UNICODE_STRING symbolicName;

        // 2. Open registry key for storing information about a
        // particular device interface instance
        RtlInitUnicodeString(&symbolicName, pSymbolicNameList);
        ntStatus = IoOpenDeviceInterfaceRegistryKey(
            &symbolicName,
            KEY_READ|KEY_WRITE,
            &hDeviceParametersKey);
        if (NT_SUCCESS(ntStatus))
        {
            OBJECT_ATTRIBUTES objAttribSubKey;
            UNICODE_STRING subKey;

            // 3. Create Capabilities key under "Device Parameters" key
            RtlInitUnicodeString(&subKey,L"Capabilities");
            InitializeObjectAttributes(&objAttribSubKey,
                &subKey,
                OBJ_KERNEL_HANDLE,
                hDeviceParametersKey,
                NULL);

            HANDLE hCapabilityKeyHandle = NULL;

            ntStatus = ZwCreateKey(&hCapabilityKeyHandle,
                    KEY_READ|KEY_WRITE|KEY_SET_VALUE,
                    &objAttribSubKey,
                    0,
                    NULL,
                    REG_OPTION_NON_VOLATILE,
                    NULL);
            if (NT_SUCCESS(ntStatus))
            {
                OBJECT_ATTRIBUTES objAttribDwordKeyVal;
                UNICODE_STRING subValDword;

                // 4. Create a DWORD value "TestCapValueDWORD" under Capabilities
                RtlInitUnicodeString(&subValDword,L"TestCapValueDWORD");

                ULONG data = 0xaaaaaaaa;

                ntStatus = ZwSetValueKey(hCapabilityKeyHandle,&subValDword,0,REG_DWORD,&data,sizeof(ULONG));
                ZwClose(hCapabilityKeyHandle);
            }
        }
        ZwClose(hDeviceParametersKey);
        ExFreePool(pSymbolicNameList);
    }

    return ntStatus;
}