Пример #1
0
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;
}
Пример #2
0
/*****************************************************************************
 * 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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
  }
}
Пример #6
0
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;
}
Пример #7
0
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;
}