MIXER_STATUS CreatePinCallback( IN PVOID Ctx, IN ULONG VirtualDeviceId, IN ULONG PinId, IN HANDLE hFilter, IN PKSPIN_CONNECT PinConnect, IN ACCESS_MASK DesiredAccess, OUT PHANDLE PinHandle) { ULONG BytesReturned; SYSAUDIO_INSTANCE_INFO InstanceInfo; NTSTATUS Status; ULONG FreeIndex; PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx; /* setup property request */ InstanceInfo.Property.Set = KSPROPSETID_Sysaudio; InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO; InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET; InstanceInfo.Flags = 0; InstanceInfo.DeviceNumber = VirtualDeviceId; /* attach to virtual device */ Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); if (!NT_SUCCESS(Status)) return MM_STATUS_UNSUCCESSFUL; /* close existing pin */ FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); /* now create the pin */ Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle); /* check for success */ if (!NT_SUCCESS(Status)) return MM_STATUS_UNSUCCESSFUL; /* store the handle */ Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex); if (!NT_SUCCESS(Status)) { /* failed to insert handle */ ZwClose(*PinHandle); return MM_STATUS_UNSUCCESSFUL; } return MM_STATUS_SUCCESS; }
/***************************************************************************** * CKsPin::Instantiate() ***************************************************************************** *//*! * @brief */ HRESULT CKsPin:: Instantiate ( IN BOOL Looped ) { HRESULT hr = S_OK; if (m_KsPinConnect) { if (m_LinkPin) { ASSERT((KSPIN_COMMUNICATION_SINK == m_LinkPin->m_PinDescriptor.Communication) || (KSPIN_COMMUNICATION_BOTH == m_LinkPin->m_PinDescriptor.Communication)); m_KsPinConnect->PinToHandle = m_LinkPin->m_Handle; } m_Looped = Looped; m_KsPinConnect->Interface.Id = m_Looped ? KSINTERFACE_STANDARD_LOOPED_STREAMING : KSINTERFACE_STANDARD_STREAMING; DWORD w32Error = KsCreatePin(m_KsFilter->m_Handle, m_KsPinConnect, GENERIC_WRITE | GENERIC_READ, &m_Handle); if (ERROR_SUCCESS != w32Error) { hr = HRESULT_FROM_WIN32(w32Error); if (SUCCEEDED(hr)) { // Sometimes the error codes don't map to error HRESULTs. hr = E_FAIL; } } if (FAILED(hr)) { _DbgPrintF(DEBUGLVL_ERROR,("[CKsPin::Instantiate] - Failed to instantiate pin. hr=0x%08x", hr)); } } return hr; }
NTSTATUS CreateMixerPinAndSetFormat( IN HANDLE KMixerHandle, IN KSPIN_CONNECT *PinConnect, IN PKSDATAFORMAT InputFormat, IN PKSDATAFORMAT OutputFormat, OUT PHANDLE MixerPinHandle) { NTSTATUS Status; HANDLE PinHandle; PFILE_OBJECT FileObject = NULL; Status = KsCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create Mixer Pin with %x\n", Status); return STATUS_UNSUCCESSFUL; } Status = ObReferenceObjectByHandle(PinHandle, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get file object with %x\n", Status); return STATUS_UNSUCCESSFUL; } Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat); if (!NT_SUCCESS(Status)) { ObDereferenceObject(FileObject); ZwClose(PinHandle); return Status; } ObDereferenceObject(FileObject); *MixerPinHandle = PinHandle; return Status; }
MIXER_STATUS MMixerOpenMidiPin( IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN ULONG DeviceId, IN ULONG PinId, IN ACCESS_MASK DesiredAccess, IN PIN_CREATE_CALLBACK CreateCallback, IN PVOID Context, OUT PHANDLE PinHandle) { PKSPIN_CONNECT PinConnect; PKSDATAFORMAT DataFormat; LPMIXER_DATA MixerData; NTSTATUS Status; MIXER_STATUS MixerStatus; MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId); if (!MixerData) return MM_STATUS_INVALID_PARAMETER; /* allocate pin connect */ PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT)); if (!PinConnect) { /* no memory */ return MM_STATUS_NO_MEMORY; } /* initialize pin connect struct */ MMixerInitializePinConnect(PinConnect, PinId); /* get offset to dataformat */ DataFormat = (PKSDATAFORMAT) (PinConnect + 1); /* initialize data format */ RtlMoveMemory(&DataFormat->MajorFormat, &KSDATAFORMAT_TYPE_MUSIC, sizeof(GUID)); RtlMoveMemory(&DataFormat->SubFormat, &KSDATAFORMAT_SUBTYPE_MIDI, sizeof(GUID)); RtlMoveMemory(&DataFormat->Specifier, &KSDATAFORMAT_SPECIFIER_NONE, sizeof(GUID)); if (CreateCallback) { /* let the callback handle the creation */ MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); } else { /* now create the pin */ Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); /* normalize status */ if (Status == STATUS_SUCCESS) MixerStatus = MM_STATUS_SUCCESS; else MixerStatus = MM_STATUS_UNSUCCESSFUL; } /* free create info */ MixerContext->Free(PinConnect); /* done */ return MixerStatus; }
static HANDLE gst_ks_video_device_create_pin (GstKsVideoDevice * self, KsVideoMediaType * media_type, gulong * num_outstanding) { GstKsVideoDevicePrivate *priv = GST_KS_VIDEO_DEVICE_GET_PRIVATE (self); HANDLE pin_handle = INVALID_HANDLE_VALUE; KSPIN_CONNECT *pin_conn = NULL; DWORD ret; GUID *propsets = NULL; gulong propsets_len; gboolean supports_mem_transport = FALSE; KSALLOCATOR_FRAMING *framing = NULL; gulong framing_size = sizeof (KSALLOCATOR_FRAMING); KSALLOCATOR_FRAMING_EX *framing_ex = NULL; gulong alignment; DWORD mem_transport; /* * Instantiate the pin. */ pin_conn = ks_video_create_pin_conn_from_media_type (media_type); GST_DEBUG ("calling KsCreatePin with pin_id = %d", media_type->pin_id); ret = KsCreatePin (priv->filter_handle, pin_conn, GENERIC_READ, &pin_handle); if (ret != ERROR_SUCCESS) goto error_create_pin; GST_DEBUG ("KsCreatePin succeeded, pin %p created", pin_handle); g_free (pin_conn); pin_conn = NULL; /* * Query the pin for supported property sets. */ if (ks_object_get_supported_property_sets (pin_handle, &propsets, &propsets_len)) { guint i; gst_ks_video_device_dump_supported_property_sets (self, "pin", propsets, propsets_len); for (i = 0; i < propsets_len; i++) { if (IsEqualGUID (&propsets[i], &KSPROPSETID_MemoryTransport)) supports_mem_transport = TRUE; } g_free (propsets); } else { GST_DEBUG ("failed to query pin for supported property sets"); } /* * Figure out how many simultanous requests it prefers. * * This is really important as it depends on the driver and the device. * Doing too few will result in poor capture performance, whilst doing too * many will make some drivers crash really horribly and leave you with a * BSOD. I've experienced the latter with older Logitech drivers. */ *num_outstanding = 0; alignment = 0; if (ks_object_get_property (pin_handle, KSPROPSETID_Connection, KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, &framing_ex, NULL)) { if (framing_ex->CountItems >= 1) { *num_outstanding = framing_ex->FramingItem[0].Frames; alignment = framing_ex->FramingItem[0].FileAlignment; } else { GST_DEBUG ("ignoring empty ALLOCATORFRAMING_EX"); } } else { GST_DEBUG ("query for ALLOCATORFRAMING_EX failed, trying " "ALLOCATORFRAMING"); if (ks_object_get_property (pin_handle, KSPROPSETID_Connection, KSPROPERTY_CONNECTION_ALLOCATORFRAMING, &framing, &framing_size)) { *num_outstanding = framing->Frames; alignment = framing->FileAlignment; } else { GST_DEBUG ("query for ALLOCATORFRAMING failed"); } } GST_DEBUG ("num_outstanding: %d alignment: 0x%08x", *num_outstanding, alignment); if (*num_outstanding == 0 || *num_outstanding > MAX_OUTSTANDING_FRAMES) { GST_DEBUG ("setting number of allowable outstanding frames to 1"); *num_outstanding = 1; } g_free (framing); g_free (framing_ex); /* * TODO: We also need to respect alignment, but for now we just align * on FILE_512_BYTE_ALIGNMENT. */ /* Set the memory transport to use. */ if (supports_mem_transport) { mem_transport = 0; /* REVISIT: use the constant here */ if (!ks_object_set_property (pin_handle, KSPROPSETID_MemoryTransport, KSPROPERTY_MEMORY_TRANSPORT, &mem_transport, sizeof (mem_transport))) { GST_DEBUG ("failed to set memory transport, sticking with the default"); } } /* * Override the clock if we have one and the pin doesn't have any either. */ if (priv->clock != NULL) { HANDLE *cur_clock_handle = NULL; gulong cur_clock_handle_size = sizeof (HANDLE); if (ks_object_get_property (pin_handle, KSPROPSETID_Stream, KSPROPERTY_STREAM_MASTERCLOCK, (gpointer *) & cur_clock_handle, &cur_clock_handle_size)) { GST_DEBUG ("current master clock handle: 0x%08x", *cur_clock_handle); CloseHandle (*cur_clock_handle); g_free (cur_clock_handle); } else { HANDLE new_clock_handle = gst_ks_clock_get_handle (priv->clock); if (ks_object_set_property (pin_handle, KSPROPSETID_Stream, KSPROPERTY_STREAM_MASTERCLOCK, &new_clock_handle, sizeof (new_clock_handle))) { gst_ks_clock_prepare (priv->clock); } else { GST_WARNING ("failed to set pin's master clock"); } } } return pin_handle; /* ERRORS */ error_create_pin: { gchar *str; gst_ks_video_device_parse_win32_error ("KsCreatePin", ret, NULL, &str); GST_ERROR ("%s", str); g_free (str); goto beach; } beach: { g_free (framing); if (ks_is_valid_handle (pin_handle)) CloseHandle (pin_handle); g_free (pin_conn); return INVALID_HANDLE_VALUE; } }
NTSTATUS NTAPI InstantiatePins( IN PKSAUDIO_DEVICE_ENTRY DeviceEntry, IN PKSPIN_CONNECT Connect, IN PDISPATCH_CONTEXT DispatchContext, IN PSYSAUDIODEVEXT DeviceExtension) { NTSTATUS Status; HANDLE RealPinHandle; PKSDATAFORMAT_WAVEFORMATEX InputFormat; PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL; PKSPIN_CONNECT MixerPinConnect = NULL; KSPIN_CINSTANCES PinInstances; DPRINT("InstantiatePins entered\n"); /* query instance count */ Status = GetPinInstanceCount(DeviceEntry, &PinInstances, Connect); if (!NT_SUCCESS(Status)) { /* failed to query instance count */ return Status; } /* can be the pin be instantiated */ if (PinInstances.PossibleCount == 0) { /* caller wanted to open an instance-less pin */ return STATUS_UNSUCCESSFUL; } /* has the maximum instance count been exceeded */ if (PinInstances.CurrentCount == PinInstances.PossibleCount) { /* FIXME pin already exists * and kmixer infrastructure is not implemented */ return STATUS_UNSUCCESSFUL; } /* Fetch input format */ InputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1); /* Let's try to create the audio irp pin */ Status = KsCreatePin(DeviceEntry->Handle, Connect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); if (!NT_SUCCESS(Status)) { /* FIXME disable kmixer */ return STATUS_UNSUCCESSFUL; } #if 0 if (!NT_SUCCESS(Status)) { /* the audio irp pin didnt accept the input format * let's compute a compatible format */ MixerPinConnect = AllocateItem(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); if (!MixerPinConnect) { /* not enough memory */ return STATUS_INSUFFICIENT_RESOURCES; } /* Zero pin connect */ RtlZeroMemory(MixerPinConnect, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); /* Copy initial connect details */ RtlMoveMemory(MixerPinConnect, Connect, sizeof(KSPIN_CONNECT)); OutputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(MixerPinConnect + 1); Status = ComputeCompatibleFormat(DeviceEntry, Connect->PinId, InputFormat, OutputFormat); if (!NT_SUCCESS(Status)) { DPRINT1("ComputeCompatibleFormat failed with %x\n", Status); FreeItem(MixerPinConnect); return Status; } /* Retry with Mixer format */ Status = KsCreatePin(DeviceEntry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); if (!NT_SUCCESS(Status)) { /* This should not fail */ DPRINT1("KsCreatePin failed with %x\n", Status); DPRINT1(" InputFormat: SampleRate %u Bits %u Channels %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample, InputFormat->WaveFormatEx.nChannels); DPRINT1("OutputFormat: SampleRate %u Bits %u Channels %u\n", OutputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels); FreeItem(MixerPinConnect); return Status; } } #endif //DeviceEntry->Pins[Connect->PinId].References = 0; /* initialize dispatch context */ DispatchContext->Handle = RealPinHandle; DispatchContext->PinId = Connect->PinId; DispatchContext->AudioEntry = DeviceEntry; DPRINT("RealPinHandle %p\n", RealPinHandle); /* Do we need to transform the audio stream */ if (OutputFormat != NULL) { /* Now create the mixer pin */ Status = CreateMixerPinAndSetFormat(DeviceExtension->KMixerHandle, MixerPinConnect, (PKSDATAFORMAT)InputFormat, (PKSDATAFORMAT)OutputFormat, &DispatchContext->hMixerPin); /* check for success */ if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create Mixer Pin with %x\n", Status); FreeItem(MixerPinConnect); } } /* done */ return Status; }
MIXER_STATUS MMixerOpenWavePin( IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN ULONG DeviceId, IN ULONG PinId, IN LPWAVEFORMATEX WaveFormatEx, IN ACCESS_MASK DesiredAccess, IN PIN_CREATE_CALLBACK CreateCallback, IN PVOID Context, OUT PHANDLE PinHandle) { PKSPIN_CONNECT PinConnect; PKSDATAFORMAT_WAVEFORMATEX DataFormat; LPMIXER_DATA MixerData; NTSTATUS Status; MIXER_STATUS MixerStatus; MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId); if (!MixerData) return MM_STATUS_INVALID_PARAMETER; /* allocate pin connect */ PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT_WAVEFORMATEX)); if (!PinConnect) { /* no memory */ return MM_STATUS_NO_MEMORY; } /* initialize pin connect struct */ MMixerInitializePinConnect(PinConnect, PinId); /* get offset to dataformat */ DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1); /* initialize with requested wave format */ MMixerInitializeDataFormat(DataFormat, WaveFormatEx); if (CreateCallback) { /* let the callback handle the creation */ MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); } else { /* now create the pin */ Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); /* normalize status */ if (Status == STATUS_SUCCESS) MixerStatus = MM_STATUS_SUCCESS; else MixerStatus = MM_STATUS_UNSUCCESSFUL; } /* free create info */ MixerContext->Free(PinConnect); /* done */ return MixerStatus; }