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/usbaud... ============================================================================== --- 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/usbaud... ============================================================================== --- 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 */