// returns format id in style of WAVEFORMATEX wFormatTag, if it possible bool FormatDetect(const WAVEFORMATEX* format, WORD* id) { if (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { const WAVEFORMATEXTENSIBLE *ext = (const WAVEFORMATEXTENSIBLE*)format; if (IS_VALID_WAVEFORMATEX_GUID(&ext->SubFormat)) { *id = EXTRACT_WAVEFORMATEX_ID(&ext->SubFormat); return true; } return false; } *id = format->wFormatTag; return true; }
/* return the maximum channel count supported by any pin on the device. if isInput is non-zero we query input pins, otherwise output pins. */ int PaWin_WDMKS_QueryFilterMaximumChannelCount( void *wcharDevicePath, int isInput ) { HANDLE deviceHandle; int pinCount, pinId, i; int result = 0; KSPIN_DATAFLOW requiredDataflowDirection = (isInput ? KSPIN_DATAFLOW_OUT : KSPIN_DATAFLOW_IN ); if( !wcharDevicePath ) return 0; deviceHandle = CreateFileW( (LPCWSTR)wcharDevicePath, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if( deviceHandle == INVALID_HANDLE_VALUE ) return 0; pinCount = GetKSFilterPinCount( deviceHandle ); for( pinId = 0; pinId < pinCount; ++pinId ) { KSPIN_COMMUNICATION communication = GetKSFilterPinPropertyCommunication( deviceHandle, pinId ); KSPIN_DATAFLOW dataflow = GetKSFilterPinPropertyDataflow( deviceHandle, pinId ); if( ( dataflow == requiredDataflowDirection ) && (( communication == KSPIN_COMMUNICATION_SINK) || ( communication == KSPIN_COMMUNICATION_BOTH)) && ( KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, KSPROPERTY_PIN_INTERFACES, &KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_STREAMING ) || KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, KSPROPERTY_PIN_INTERFACES, &KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_LOOPED_STREAMING ) ) && KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, KSPROPERTY_PIN_MEDIUMS, &KSMEDIUMSETID_Standard, KSMEDIUM_STANDARD_DEVIO ) ) { KSMULTIPLE_ITEM* item = NULL; if( WdmGetPinPropertyMulti( deviceHandle, pinId, KSPROPERTY_PIN_DATARANGES, &item ) == paNoError ) { KSDATARANGE *dataRange = (KSDATARANGE*)(item+1); for( i=0; i < item->Count; ++i ){ if( IS_VALID_WAVEFORMATEX_GUID(&dataRange->SubFormat) || memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID) ) == 0 || memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID) ) == 0 || ( ( memcmp( (void*)&dataRange->MajorFormat, (void*)&KSDATAFORMAT_TYPE_AUDIO, sizeof(GUID) ) == 0 ) && ( memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_WILDCARD, sizeof(GUID) ) == 0 ) ) ) { KSDATARANGE_AUDIO *dataRangeAudio = (KSDATARANGE_AUDIO*)dataRange; /* printf( ">>> %d %d %d %d %S\n", isInput, dataflow, communication, dataRangeAudio->MaximumChannels, devicePath ); if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, sizeof(GUID) ) == 0 ) printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WAVEFORMATEX\n" ); else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_DSOUND, sizeof(GUID) ) == 0 ) printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_DSOUND\n" ); else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WILDCARD, sizeof(GUID) ) == 0 ) printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WILDCARD\n" ); else printf( "\tspecifier: ?\n" ); */ /* We assume that very high values for MaximumChannels are not useful and indicate that the driver isn't prepared to tell us the real number of channels which it supports. */ if( dataRangeAudio->MaximumChannels < 0xFFFFUL && (int)dataRangeAudio->MaximumChannels > result ) result = (int)dataRangeAudio->MaximumChannels; } dataRange = (KSDATARANGE*)( ((char*)dataRange) + dataRange->FormatSize); } PaUtil_FreeMemory( item ); } } } CloseHandle( deviceHandle ); return result; }
//============================================================================= NTSTATUS CMiniportWaveCyclic::ValidateFormat ( IN ULONG nPin, IN PKSDATAFORMAT pDataFormat ) /*++ Routine Description: Validates that the given dataformat is valid. This overwrites BaseWave's ValidateFormat and includes checks for AC3 format. Arguments: pDataFormat - The dataformat for validation. Return Value: NT status code. --*/ { PAGED_CODE(); DPF_ENTER(("[CMiniportWaveCyclic::ValidateFormat]")); NTSTATUS ntStatus = STATUS_INVALID_PARAMETER; PWAVEFORMATEX pwfx; pwfx = GetWaveFormatEx(pDataFormat); if (pwfx) { if (IS_VALID_WAVEFORMATEX_GUID(&pDataFormat->SubFormat)) { USHORT wfxID = EXTRACT_WAVEFORMATEX_ID(&pDataFormat->SubFormat); if ((wfxID == WAVE_FORMAT_PCM) || ((wfxID == WAVE_FORMAT_DOLBY_AC3_SPDIF) && ((nPin == KSPIN_WAVE_SPDIF_CAPTURE_HOST) || (nPin == KSPIN_WAVE_SPDIF_RENDER_HOST)))) { if ( (pDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)) && (pwfx->cbSize == 0) && (pwfx->nChannels <= MAX_CHANNELS ) && (pwfx->wBitsPerSample >= MIN_BITS_PER_SAMPLE)&& (pwfx->wBitsPerSample <= MAX_BITS_PER_SAMPLE)&& (pwfx->nSamplesPerSec >= MIN_SAMPLE_RATE) && (pwfx->nSamplesPerSec <= MAX_SAMPLE_RATE) ) { ntStatus = STATUS_SUCCESS; } else { DPF(D_TERSE, ("Invalid format")); } } else { DPF(D_TERSE, ("Invalid format tag")); } } else { DPF(D_TERSE, ("Invalid pDataFormat->SubFormat!") ); } } return ntStatus; } // ValidateFormat