인코더 코드 예제
다음 코드 예제는 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;
}