Author: janderwald
Date: Sat Nov 5 16:38:59 2016
New Revision: 73138
URL:
http://svn.reactos.org/svn/reactos?rev=73138&view=rev
Log:
[USBAUDIO]
- store remaining audio bytes in a common buffer, which will be sent on next request
- fixes some of audio distortion issues
Modified:
trunk/reactos/drivers/usb/usbaudio/pin.c
trunk/reactos/drivers/usb/usbaudio/usbaudio.c
trunk/reactos/drivers/usb/usbaudio/usbaudio.h
Modified: trunk/reactos/drivers/usb/usbaudio/pin.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbaudio/pin.c…
==============================================================================
--- trunk/reactos/drivers/usb/usbaudio/pin.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbaudio/pin.c [iso-8859-1] Sat Nov 5 16:38:59 2016
@@ -308,7 +308,73 @@
} while (Count);
}
-
+NTSTATUS
+RenderInitializeUrbAndIrp(
+ IN PKSPIN Pin,
+ IN PPIN_CONTEXT PinContext,
+ IN OUT PIRP Irp,
+ IN PVOID TransferBuffer,
+ IN ULONG TransferBufferSize,
+ IN ULONG PacketSize)
+{
+ ULONG Index, PacketCount;
+ PURB Urb;
+ PIO_STACK_LOCATION IoStack;
+
+ /* initialize irp */
+ IoInitializeIrp(Irp,
IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize),
PinContext->DeviceExtension->LowerDevice->StackSize);
+
+ /* set irp members */
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+ Irp->IoStatus.Information = 0;
+ Irp->Flags = 0;
+ Irp->UserBuffer = NULL;
+
+ /* init stack location */
+ IoStack = IoGetNextIrpStackLocation(Irp);
+ IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
+ IoStack->Parameters.Others.Argument2 = NULL;
+ IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ IoStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
+
+ /* set completion routine */
+ IoSetCompletionRoutine(Irp, UsbAudioRenderComplete, Pin, TRUE, TRUE, TRUE);
+
+ /* calculate packet count */
+ PacketCount = TransferBufferSize / PacketSize;
+ ASSERT(TransferBufferSize % PacketSize == 0);
+
+ /* lets allocate urb */
+ Urb = (PURB)AllocFunction(GET_ISO_URB_SIZE(PacketCount));
+ if (!Urb)
+ {
+ /* no memory */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* init urb */
+ Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
+ Urb->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(PacketCount);
+ Urb->UrbIsochronousTransfer.PipeHandle =
PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle;
+ Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT |
USBD_START_ISO_TRANSFER_ASAP;
+ Urb->UrbIsochronousTransfer.TransferBufferLength = TransferBufferSize;
+ Urb->UrbIsochronousTransfer.TransferBuffer = TransferBuffer;
+ Urb->UrbIsochronousTransfer.NumberOfPackets = PacketCount;
+ Urb->UrbIsochronousTransfer.StartFrame = 0;
+
+ for (Index = 0; Index < PacketCount; Index++)
+ {
+ Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * PacketSize;
+ }
+
+ /* store urb */
+ IoStack->Parameters.Others.Argument1 = Urb;
+ Irp->Tail.Overlay.DriverContext[0] = Urb;
+
+
+ /* done */
+ return STATUS_SUCCESS;
+}
VOID
CaptureInitializeUrbAndIrp(
@@ -567,12 +633,27 @@
ULONG Index;
PIRP Irp;
PPIN_CONTEXT PinContext;
+ PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
PIO_STACK_LOCATION IoStack;
DPRINT1("InitStreamPin\n");
/* get pin context */
PinContext = Pin->Context;
+
+ /* allocate 1 sec buffer */
+ WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
+ PinContext->Buffer =
AllocFunction(WaveFormatEx->WaveFormatEx.nAvgBytesPerSec);
+ if (!PinContext->Buffer)
+ {
+ /* no memory */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* init buffer size*/
+ PinContext->BufferSize = WaveFormatEx->WaveFormatEx.nAvgBytesPerSec;
+ PinContext->BufferOffset = 0;
+ PinContext->BufferLength = 0;
/* init irps */
for (Index = 0; Index < 12; Index++)
@@ -706,7 +787,8 @@
KIRQL OldLevel;
PKSSTREAM_POINTER StreamPointerClone;
NTSTATUS Status;
-
+ PURB Urb;
+
/* get pin context */
Pin = Context;
PinContext = Pin->Context;
@@ -717,6 +799,12 @@
/* get streampointer */
StreamPointerClone = Irp->Tail.Overlay.DriverContext[1];
+ /* get urb */
+ Urb = Irp->Tail.Overlay.DriverContext[0];
+
+ /* and free it */
+ FreeFunction(Urb);
+
/* acquire lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
@@ -726,15 +814,18 @@
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status) && StreamPointerClone)
{
/* set status code because it failed */
- //KsStreamPointerSetStatusCode(StreamPointerClone, STATUS_DEVICE_DATA_ERROR);
+ KsStreamPointerSetStatusCode(StreamPointerClone, STATUS_DEVICE_DATA_ERROR);
DPRINT1("UsbAudioRenderComplete failed with %x\n", Status);
}
- /* lets delete the stream pointer clone */
- KsStreamPointerDelete(StreamPointerClone);
+ if (StreamPointerClone)
+ {
+ /* lets delete the stream pointer clone */
+ KsStreamPointerDelete(StreamPointerClone);
+ }
/* done */
return STATUS_MORE_PROCESSING_REQUIRED;
@@ -789,6 +880,36 @@
return STATUS_MORE_PROCESSING_REQUIRED;
}
+PIRP
+PinGetIrpFromReadyList(
+ IN PKSPIN Pin)
+{
+ PPIN_CONTEXT PinContext;
+ PLIST_ENTRY CurEntry;
+ KIRQL OldLevel;
+ PIRP Irp = NULL;
+
+ /* get pin context */
+ PinContext = Pin->Context;
+
+ /* acquire spin lock */
+ KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
+
+ if (!IsListEmpty(&PinContext->IrpListHead))
+ {
+ /* remove entry from list */
+ CurEntry = RemoveHeadList(&PinContext->IrpListHead);
+
+ /* get irp offset */
+ Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
+ }
+
+ /* release lock */
+ KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
+
+ return Irp;
+}
+
NTSTATUS
PinRenderProcess(
IN PKSPIN Pin)
@@ -796,13 +917,10 @@
PKSSTREAM_POINTER LeadingStreamPointer;
PKSSTREAM_POINTER CloneStreamPointer;
NTSTATUS Status;
- KIRQL OldLevel;
PPIN_CONTEXT PinContext;
- PURB Urb;
- ULONG PacketCount, TotalPacketSize, Index;
+ ULONG PacketCount, TotalPacketSize, Offset;
PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
- PIO_STACK_LOCATION IoStack;
- PLIST_ENTRY CurEntry;
+ PUCHAR TransferBuffer;
PIRP Irp = NULL;
//DPRINT1("PinRenderProcess\n");
@@ -817,26 +935,14 @@
{
Status = KsStreamPointerAdvance(LeadingStreamPointer);
DPRINT1("Advancing Streampointer\n");
- }
+ }
/* get pin context */
PinContext = Pin->Context;
- /* acquire spin lock */
- KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
-
- if (!IsListEmpty(&PinContext->IrpListHead))
- {
- /* remove entry from list */
- CurEntry = RemoveHeadList(&PinContext->IrpListHead);
-
- /* get irp offset */
- Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
- }
-
- /* release lock */
- KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
+ /* get irp from ready list */
+ Irp = PinGetIrpFromReadyList(Pin);
if (!Irp)
{
@@ -856,65 +962,86 @@
return STATUS_SUCCESS;
}
-
- /* initialize irp */
- IoInitializeIrp(Irp,
IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize),
PinContext->DeviceExtension->LowerDevice->StackSize);
-
- Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
- Irp->IoStatus.Information = 0;
- Irp->Flags = 0;
- Irp->UserBuffer = NULL;
-
- IoStack = IoGetNextIrpStackLocation(Irp);
- IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
- IoStack->Parameters.Others.Argument2 = NULL;
- IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
- IoStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
-
- IoSetCompletionRoutine(Irp, UsbAudioRenderComplete, Pin, TRUE, TRUE, TRUE);
-
/* calculate packet count */
/* FIXME support various sample rates */
WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
TotalPacketSize = WaveFormatEx->WaveFormatEx.nAvgBytesPerSec / 1000;
- ASSERT(TotalPacketSize <=
PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize);
+
+ /* init transfer buffer*/
+ TransferBuffer = CloneStreamPointer->StreamHeader->Data;
+
+ Offset = 0;
+
+ /* are there bytes from previous request*/
+ if (PinContext->BufferLength)
+ {
+ ASSERT(PinContext->BufferLength < TotalPacketSize);
+
+ /* calculate offset*/
+ Offset = TotalPacketSize - PinContext->BufferLength;
+
+ if (PinContext->BufferOffset + Offset >= PinContext->BufferSize)
+ {
+ RtlMoveMemory(PinContext->Buffer,
&PinContext->Buffer[PinContext->BufferOffset - PinContext->BufferLength],
PinContext->BufferLength);
+ PinContext->BufferOffset = PinContext->BufferLength;
+ }
+
+ /* copy audio bytes */
+ RtlCopyMemory(&PinContext->Buffer[PinContext->BufferOffset],
TransferBuffer, Offset);
+
+ /* init irp*/
+ Status = RenderInitializeUrbAndIrp(Pin, PinContext, Irp,
&PinContext->Buffer[PinContext->BufferOffset-PinContext->BufferLength],
TotalPacketSize, TotalPacketSize);
+ if (NT_SUCCESS(Status))
+ {
+ /* render audio bytes */
+ Status = IoCallDriver(PinContext->LowerDevice, Irp);
+ }
+ else
+ {
+ ASSERT(FALSE);
+ }
+
+ PinContext->BufferLength = 0;
+ PinContext->BufferOffset += Offset;
+
+ /* get new irp from ready list */
+ Irp = PinGetIrpFromReadyList(Pin);
+ ASSERT(Irp);
+
+ }
/* FIXME correct MaximumPacketSize ? */
- PacketCount = CloneStreamPointer->OffsetIn.Remaining / TotalPacketSize;
-
- ASSERT(PacketCount < 255);
-
- Urb = (PURB)AllocFunction(GET_ISO_URB_SIZE(PacketCount));
- ASSERT(Urb);
-
- /* init urb */
- Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
- Urb->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(PacketCount);
- Urb->UrbIsochronousTransfer.PipeHandle =
PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle;
- Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT |
USBD_START_ISO_TRANSFER_ASAP;
- Urb->UrbIsochronousTransfer.TransferBufferLength = PacketCount * TotalPacketSize;
- Urb->UrbIsochronousTransfer.TransferBuffer =
CloneStreamPointer->StreamHeader->Data;
- Urb->UrbIsochronousTransfer.NumberOfPackets = PacketCount;
- Urb->UrbIsochronousTransfer.StartFrame = 0;
-
- for (Index = 0; Index < PacketCount; Index++)
- {
- Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index *
TotalPacketSize;
- }
-
- /* store urb */
- IoStack = IoGetNextIrpStackLocation(Irp);
- IoStack->Parameters.Others.Argument1 = Urb;
-
- /* store in irp context */
- Irp->Tail.Overlay.DriverContext[0] = Urb;
- Irp->Tail.Overlay.DriverContext[1] = CloneStreamPointer;
-
- Status = IoCallDriver(PinContext->LowerDevice, Irp);
+ PacketCount = (CloneStreamPointer->OffsetIn.Remaining - Offset) /
TotalPacketSize;
+
+ Status = RenderInitializeUrbAndIrp(Pin, PinContext, Irp, &TransferBuffer[Offset],
PacketCount * TotalPacketSize, TotalPacketSize);
+ if (NT_SUCCESS(Status))
+ {
+ /* store in irp context */
+ Irp->Tail.Overlay.DriverContext[1] = CloneStreamPointer;
+
+ if ((PacketCount * TotalPacketSize) + Offset <
CloneStreamPointer->OffsetIn.Remaining)
+ {
+ /* calculate remaining buffer bytes */
+ PinContext->BufferLength = CloneStreamPointer->OffsetIn.Remaining -
((PacketCount * TotalPacketSize) + Offset);
+
+ /* check for overflow */
+ if (PinContext->BufferOffset + Offset >= PinContext->BufferSize)
+ {
+ /* reset buffer offset*/
+ PinContext->BufferOffset = 0;
+ }
+ RtlCopyMemory(&PinContext->Buffer[PinContext->BufferOffset],
&TransferBuffer[(PacketCount * TotalPacketSize) + Offset],
PinContext->BufferLength);
+ PinContext->BufferOffset += PinContext->BufferLength;
+ }
+
+ /* render audio bytes */
+ Status = IoCallDriver(PinContext->LowerDevice, Irp);
+ }
+
/* unlock stream pointer and finish*/
KsStreamPointerUnlock(LeadingStreamPointer, TRUE);
- return Status;
+ return STATUS_PENDING;
}
NTSTATUS
Modified: trunk/reactos/drivers/usb/usbaudio/usbaudio.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbaudio/usbau…
==============================================================================
--- trunk/reactos/drivers/usb/usbaudio/usbaudio.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbaudio/usbaudio.c [iso-8859-1] Sat Nov 5 16:38:59 2016
@@ -324,7 +324,7 @@
Status = USBAudioStartDevice(Device);
if (NT_SUCCESS(Status))
{
- /* TODO build filter topology and pin descriptors and retrieve interface */
+ /* TODO retrieve interface */
Status = USBAudioCreateFilterContext(Device);
}
}
Modified: trunk/reactos/drivers/usb/usbaudio/usbaudio.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbaudio/usbau…
==============================================================================
--- trunk/reactos/drivers/usb/usbaudio/usbaudio.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbaudio/usbaudio.h [iso-8859-1] Sat Nov 5 16:38:59 2016
@@ -200,12 +200,13 @@
KSPIN_LOCK IrpListLock; /* irp list lock*/
PUCHAR Buffer; /* iso buffer*/
ULONG BufferSize; /* iso buffer size */
+ ULONG BufferOffset; /* buffer offset */
+ ULONG BufferLength; /* remaining render
bytes */
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; /* interface descriptor
*/
WORK_QUEUE_ITEM CaptureWorkItem; /* work item */
PKSWORKER CaptureWorker; /* capture worker */
WORK_QUEUE_ITEM StarvationWorkItem; /* work item */
PKSWORKER StarvationWorker; /* capture worker */
- ULONG BufferOffset;
}PIN_CONTEXT, *PPIN_CONTEXT;
/* filter.c */