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/wdmaud... ============================================================================== --- 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/p... ============================================================================== --- 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/p... ============================================================================== --- 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/p... ============================================================================== --- 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/wd... ============================================================================== --- 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 {