Author: janderwald
Date: Sun Mar 8 19:25:28 2009
New Revision: 39907
URL:
http://svn.reactos.org/svn/reactos?rev=39907&view=rev
Log:
- Wait for the APC in wdmaud.drv
- Queue ~ one second of audio data before starting to stream
- Check if an audio pin is already open and re-use it in that case
Modified:
trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h
trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
trunk/reactos/drivers/wdm/audio/sysaudio/control.c
Modified: trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wdmaud.drv/wdmau…
==============================================================================
--- trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c [iso-8859-1] Sun Mar 8 19:25:28 2009
@@ -309,10 +309,8 @@
}
else
{
- /* HACK
- * The CompletionRoutine should be called by the system
- */
- CompletionRoutine(0, Length, (LPOVERLAPPED)Overlap);
+ WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
+
}
return MMSYSERR_NOERROR;
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h [iso-8859-1] Sun Mar 8
19:25:28 2009
@@ -193,6 +193,7 @@
STDMETHOD_(NTSTATUS, Init)(THIS_
IN KSPIN_CONNECT *ConnectDetails,
+ IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject);
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
@@ -211,7 +212,7 @@
STDMETHOD_(ULONG, MinMappings)(THIS);
- STDMETHOD_(ULONG, MaxMappings)(THIS);
+ STDMETHOD_(BOOL, MinimumDataAvailable)(THIS);
};
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c [iso-8859-1] Sun Mar 8
19:25:28 2009
@@ -18,8 +18,6 @@
struct _IRP_MAPPING_ * Next;
}IRP_MAPPING, *PIRP_MAPPING;
-#define MAX_MAPPING (100)
-
typedef struct
{
IIrpQueueVtbl *lpVtbl;
@@ -27,9 +25,10 @@
LONG ref;
ULONG CurrentOffset;
- ULONG NextMapping;
LONG NumMappings;
- IN KSPIN_CONNECT *ConnectDetails;
+ ULONG NumDataAvailable;
+ KSPIN_CONNECT *ConnectDetails;
+ PKSDATAFORMAT_WAVEFORMATEX DataFormat;
KDPC Dpc;
PIRP_MAPPING FirstMap;
@@ -38,7 +37,7 @@
ULONG DpcActive;
PIRP_MAPPING FreeMapHead;
PIRP_MAPPING FreeMapTail;
-
+ ULONG FreeDataSize;
LONG FreeCount;
}IIrpQueueImpl;
@@ -63,20 +62,27 @@
{
NextMapping = CurMapping->Next;
- CurMapping->Irp->IoStatus.Information =
CurMapping->Header->DataUsed;
- CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
+ This->FreeDataSize -= CurMapping->Header->DataUsed;
+
+ if (CurMapping->Irp)
+ {
+ CurMapping->Irp->IoStatus.Information =
CurMapping->Header->DataUsed;
+ CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
+ }
ExFreePool(CurMapping->Header->Data);
ExFreePool(CurMapping->Header);
+
ExFreePool(CurMapping);
CurMapping = NextMapping;
InterlockedDecrement(&This->FreeCount);
+
Count++;
}
This->DpcActive = FALSE;
- DPRINT1("Freed %u Buffers / IRP\n", Count);
+ DPRINT1("Freed %u Buffers / IRP Available Mappings %u\n", Count,
This->NumMappings);
}
@@ -132,11 +138,14 @@
IIrpQueue_fnInit(
IN IIrpQueue *iface,
IN KSPIN_CONNECT *ConnectDetails,
+ IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
This->ConnectDetails = ConnectDetails;
+ This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
+
KeInitializeDpc(&This->Dpc, DpcRoutine, (PVOID)This);
return STATUS_SUCCESS;
@@ -161,6 +170,8 @@
Mapping->Irp = Irp;
Mapping->Next = NULL;
+ DPRINT1("FirstMap %p LastMap %p NumMappings %u\n", This->FirstMap,
This->LastMap, This->NumMappings);
+
if (!This->FirstMap)
This->FirstMap = Mapping;
else
@@ -170,8 +181,16 @@
InterlockedIncrement(&This->NumMappings);
- DPRINT1("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu\n",
This->NumMappings, Mapping->Header->DataUsed);
-
+ if (Irp)
+ {
+ Irp->IoStatus.Status = STATUS_PENDING;
+ Irp->IoStatus.Information = 0;
+ IoMarkIrpPending(Irp);
+ }
+
+ This->NumDataAvailable += Mapping->Header->DataUsed;
+
+ DPRINT1("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu
NumDataAvailable %lu\n", This->NumMappings, Mapping->Header->DataUsed,
This->NumDataAvailable);
return STATUS_SUCCESS;
}
@@ -221,8 +240,13 @@
This->FreeMapTail = Mapping;
Mapping->Next = NULL;
-
- if (This->FreeCount > iface->lpVtbl->MinMappings(iface) &&
This->DpcActive == FALSE)
+ This->FreeDataSize += Mapping->Header->DataUsed;
+ InterlockedDecrement(&This->NumMappings);
+ This->NumDataAvailable -= Mapping->Header->DataUsed;
+
+
+ if ((This->FreeDataSize >
This->DataFormat->WaveFormatEx.nAvgBytesPerSec || This->FreeCount > 25)
&&
+ This->DpcActive == FALSE)
{
Mapping = This->FreeMapHead;
This->FreeMapHead = NULL;
@@ -245,19 +269,30 @@
ULONG
NTAPI
-IIrpQueue_fnMaxMappings(
- IN IIrpQueue *iface)
-{
- return MAX_MAPPING;
-}
-
-ULONG
-NTAPI
IIrpQueue_fnMinMappings(
IN IIrpQueue *iface)
{
- return MAX_MAPPING / 4;
-}
+ return 25;
+}
+
+
+BOOL
+NTAPI
+IIrpQueue_fnMinimumDataAvailable(
+ IN IIrpQueue *iface)
+{
+ BOOL Result;
+ IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
+
+ if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec <
This->NumDataAvailable)
+ Result = TRUE;
+ else
+ Result = FALSE;
+
+ return Result;
+}
+
+
static IIrpQueueVtbl vt_IIrpQueue =
{
@@ -270,7 +305,7 @@
IIrpQueue_fnUpdateMapping,
IIrpQueue_fnNumMappings,
IIrpQueue_fnMinMappings,
- IIrpQueue_fnMaxMappings
+ IIrpQueue_fnMinimumDataAvailable
};
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1]
(original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] Sun Mar
8 19:25:28 2009
@@ -27,6 +27,7 @@
ULONG ActiveIrpOffset;
ULONG DelayedRequestInProgress;
ULONG RetryCount;
+ ULONG FrameSize;
}IPortPinWaveCyclicImpl;
@@ -172,16 +173,16 @@
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface,
IPortPinWaveCyclicImpl, lpVtblServiceSink);
-
Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer,
&BufferSize);
if (!NT_SUCCESS(Status))
{
This->RetryCount++;
if (This->RetryCount > 30)
{
- DPRINT1("Stopping\n");
+ DPRINT1("Stopping %u\n",
This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
This->RetryCount = 0;
+ This->State = KSSTATE_STOP;
return;
}
DPRINT("IServiceSink_fnRequestService> Waiting for mapping\n");
@@ -380,7 +381,10 @@
if (This->Stream)
{
- Status = This->Stream->lpVtbl->SetFormat(This->Stream,
DataFormat);
+ This->Stream->lpVtbl->SetState(This->Stream,
KSSTATE_STOP);
+ This->State = KSSTATE_STOP;
+
+ Status = This->Stream->lpVtbl->SetFormat(This->Stream,
NewDataFormat);
if (NT_SUCCESS(Status))
{
if (This->Format)
@@ -646,25 +650,44 @@
{
NTSTATUS Status;
PCONTEXT_WRITE Packet;
+ PIRP Irp;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
DPRINT1("IPortPinWaveCyclic_fnFastWrite entered\n");
Packet = (PCONTEXT_WRITE)Buffer;
-
- Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer,
Length, Packet->Irp);
+ //if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
+ // Irp = Packet->Irp;
+ //else
+ Irp = NULL;
+
+ Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer,
Length, Irp);
if (!NT_SUCCESS(Status))
return FALSE;
- if ((This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) >
This->IrpQueue->lpVtbl->MinMappings(This->IrpQueue)) &&
- This->State != KSSTATE_RUN)
+ if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE
&& This->State != KSSTATE_RUN)
{
/* some should initiate a state request but didnt do it */
DPRINT1("Starting stream with %lu mappings\n",
This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
+
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_RUN);
This->State = KSSTATE_RUN;
+ }
+
+ if (!Irp)
+ {
+ DPRINT1("Completing Irp %p\n", Packet->Irp);
+
+ Packet->Irp->IoStatus.Status = STATUS_SUCCESS;
+ Packet->Irp->IoStatus.Information = Packet->Header.DataUsed;
+ IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT);
+ StatusBlock->Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ StatusBlock->Status = STATUS_PENDING;
}
return TRUE;
@@ -697,22 +720,21 @@
DeviceObject = GetDeviceObject(Port);
+ DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
+
+ DPRINT("IPortPinWaveCyclic_fnInit entered\n");
+
+ This->Format = ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize,
TAG_PORTCLASS);
+ if (!This->Format)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize);
Status = NewIrpQueue(&This->IrpQueue);
if (!NT_SUCCESS(Status))
return Status;
- Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
DeviceObject);
-
- DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
-
- DPRINT("IPortPinWaveCyclic_fnInit entered\n");
-
- This->Format = ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize,
TAG_PORTCLASS);
- if (!This->Format)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize);
+ Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
DataFormat, DeviceObject);
Status = This->Miniport->lpVtbl->NewStream(This->Miniport,
&This->Stream,
@@ -729,7 +751,7 @@
if (!NT_SUCCESS(Status))
return Status;
- Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup,
+ Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup,
(PSERVICESINK)&This->lpVtblServiceSink);
if (!NT_SUCCESS(Status))
{
@@ -742,6 +764,8 @@
This->CommonBufferOffset = 0;
This->CommonBufferSize =
This->DmaChannel->lpVtbl->AllocatedBufferSize(This->DmaChannel);
This->CommonBuffer =
This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel);
+
+ //Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10,
&This->FrameSize);
return STATUS_SUCCESS;
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] Sun Mar 8
19:25:28 2009
@@ -733,10 +733,8 @@
KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet,
sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, KernelMode);
- Irp->IoStatus.Status = STATUS_PENDING;
- Irp->IoStatus.Information = 0;
- IoMarkIrpPending(Irp);
- return STATUS_PENDING;
+
+ return IoStatusBlock.Status;
//return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
}
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/control.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] Sun Mar 8 19:25:28
2009
@@ -299,7 +299,7 @@
else
{
AudioClient->Devs[AudioClient->NumDevices
-1].ClientHandles[NumHandels].bHandle = FALSE;
- AudioClient->Devs[AudioClient->NumDevices
-1].ClientHandles[NumHandels].hPin = NULL;
+ AudioClient->Devs[AudioClient->NumDevices
-1].ClientHandles[NumHandels].hPin = VirtualPinHandle;
AudioClient->Devs[AudioClient->NumDevices
-1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
}
@@ -410,6 +410,43 @@
return SetIrpIoStatus(Irp, Status, BytesReturned);
}
}
+
+NTSTATUS
+SetPinFormat(
+ PKSAUDIO_DEVICE_ENTRY Entry,
+ KSPIN_CONNECT * PinConnect,
+ ULONG Length)
+{
+ KSP_PIN PinRequest;
+ PFILE_OBJECT FileObject;
+ ULONG BytesReturned;
+ NTSTATUS Status;
+
+ /* re-using pin */
+ PinRequest.Property.Set = KSPROPSETID_Connection;
+ PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
+ PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
+ PinRequest.PinId = PinConnect->PinId;
+
+ /* get pin file object */
+ Status = ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle,
+ GENERIC_READ | GENERIC_WRITE,
+ IoFileObjectType, KernelMode,
(PVOID*)&FileObject, NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to get pin file object with %x\n", Status);
+ return Status;
+ }
+
+ Length -= sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
+ Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
(PVOID)&PinRequest, sizeof(KSPROPERTY),
+ (PVOID)(PinConnect + 1), Length,
&BytesReturned);
+ ObDereferenceObject(FileObject);
+
+ return Status;
+}
+
NTSTATUS
HandleSysAudioFilterPinCreation(
@@ -429,9 +466,9 @@
NTSTATUS Status;
KSPIN_CINSTANCES PinInstances;
PIO_WORKITEM WorkItem;
- PFILE_OBJECT FileObject;
PPIN_WORKER_CONTEXT WorkerContext;
PDISPATCH_CONTEXT DispatchContext;
+ ULONG Index, SubIndex;
IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -456,8 +493,7 @@
/* get client context */
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
- if (!ClientInfo || !ClientInfo->NumDevices || !ClientInfo->Devs ||
- ClientInfo->Devs[ClientInfo->NumDevices-1].DeviceId !=
InstanceInfo->DeviceNumber)
+ if (!ClientInfo || !ClientInfo->NumDevices || !ClientInfo->Devs)
{
/* we have a problem */
KeBugCheckEx(0, 0, 0, 0, 0);
@@ -506,6 +542,30 @@
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
{
+ for (Index = 0; Index < ClientInfo->NumDevices; Index++)
+ {
+ if (ClientInfo->Devs[Index].DeviceId == InstanceInfo->DeviceNumber)
+ {
+ if (ClientInfo->Devs[Index].ClientHandlesCount)
+ {
+ for(SubIndex = 0; SubIndex <
ClientInfo->Devs[Index].ClientHandlesCount; SubIndex++)
+ {
+ if (ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId ==
PinConnect->PinId)
+ {
+ /* reuse opened pin */
+ Length =
IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSPIN_CONNECT) +
sizeof(SYSAUDIO_INSTANCE_INFO);
+ Status = SetPinFormat(Entry, PinConnect, Length);
+ DPRINT1("Reusing instance handle Status %x\n",
Status);
+
ASSERT(ClientInfo->Devs[Index].ClientHandles[SubIndex].bHandle == FALSE);
+ *((PHANDLE)Irp->UserBuffer) =
ClientInfo->Devs[Index].ClientHandles[SubIndex].hPin;
+ return SetIrpIoStatus(Irp, Status, sizeof(HANDLE));
+ }
+ }
+ }
+
+ }
+ }
+
/* pin already exists */
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
if (Entry->Pins[PinConnect->PinId].References > 1)
@@ -550,39 +610,14 @@
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
{
/* re-using pin */
- PinRequest.Property.Set = KSPROPSETID_Connection;
- PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
- PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
-
- /* get pin file object */
- Status =
ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle,
- GENERIC_READ | GENERIC_WRITE,
- IoFileObjectType, KernelMode,
(PVOID*)&FileObject, NULL);
-
+ Status = SetPinFormat(Entry, PinConnect, Length);
if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to get pin file object with %x\n", Status);
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
ExFreePool(DispatchContext);
return SetIrpIoStatus(Irp, Status, 0);
}
-
- Length -= sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
- Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
(PVOID)&PinRequest, sizeof(KSPROPERTY),
- (PVOID)(PinConnect + 1), Length,
&BytesReturned);
-
- ObDereferenceObject(FileObject);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to set format with Status %x\n", Status);
- IoFreeWorkItem(WorkItem);
- ExFreePool(WorkerContext);
- ExFreePool(DispatchContext);
- return SetIrpIoStatus(Irp, Status, 0);
- }
-
}
else
{