- Implement looped streaming (needed for dsound bringup)

- Implement GetPosition handler for looped streaming, WIP

svn path=/trunk/; revision=43868
This commit is contained in:
Johannes Anderwald 2009-10-31 08:26:26 +00:00
parent a51c149046
commit 46c8396918
5 changed files with 80 additions and 50 deletions

View file

@ -322,9 +322,8 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
IN PVOID SilenceBuffer) PURE; IN PVOID SilenceBuffer) PURE;
STDMETHOD_(NTSTATUS, AddMapping)(THIS_ STDMETHOD_(NTSTATUS, AddMapping)(THIS_
IN PUCHAR Buffer, IN PIRP Irp,
IN ULONG BufferSize, OUT PULONG Data) PURE;
IN PIRP Irp) PURE;
STDMETHOD_(NTSTATUS, GetMapping)(THIS_ STDMETHOD_(NTSTATUS, GetMapping)(THIS_
OUT PUCHAR * Buffer, OUT PUCHAR * Buffer,
@ -372,9 +371,8 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
IN PVOID SilenceBuffer); \ IN PVOID SilenceBuffer); \
\ \
STDMETHODIMP_(NTSTATUS) AddMapping(THIS_ \ STDMETHODIMP_(NTSTATUS) AddMapping(THIS_ \
IN PUCHAR Buffer, \ IN PIRP Irp, \
IN ULONG BufferSize, \ OUT PULONG Data); \
IN PIRP Irp); \
\ \
STDMETHODIMP_(NTSTATUS) GetMapping(THIS_ \ STDMETHODIMP_(NTSTATUS) GetMapping(THIS_ \
OUT PUCHAR * Buffer, \ OUT PUCHAR * Buffer, \

View file

@ -39,7 +39,7 @@ protected:
LONG m_NumMappings; LONG m_NumMappings;
ULONG m_NumDataAvailable; ULONG m_NumDataAvailable;
BOOL m_StartStream; BOOL m_StartStream;
KSPIN_CONNECT * m_ConnectDetails; PKSPIN_CONNECT m_ConnectDetails;
PKSDATAFORMAT_WAVEFORMATEX m_DataFormat; PKSDATAFORMAT_WAVEFORMATEX m_DataFormat;
KSPIN_LOCK m_IrpListLock; KSPIN_LOCK m_IrpListLock;
@ -110,9 +110,8 @@ CIrpQueue::Init(
NTSTATUS NTSTATUS
NTAPI NTAPI
CIrpQueue::AddMapping( CIrpQueue::AddMapping(
IN PUCHAR Buffer, IN PIRP Irp,
IN ULONG BufferSize, OUT PULONG Data)
IN PIRP Irp)
{ {
PKSSTREAM_HEADER Header; PKSSTREAM_HEADER Header;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
@ -125,8 +124,6 @@ CIrpQueue::AddMapping(
// get current irp stack location // get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp); IoStack = IoGetCurrentIrpStackLocation(Irp);
PC_ASSERT(!Buffer);
if (!Irp->MdlAddress) if (!Irp->MdlAddress)
{ {
// ioctl from KsStudio // ioctl from KsStudio
@ -172,8 +169,8 @@ CIrpQueue::AddMapping(
NumData = 0; NumData = 0;
// prepare all headers // prepare all headers
for(Index = 0; Index < NumHeaders; Index++) for(Index = 0; Index < NumHeaders; Index++)
{ {
// sanity checks // sanity checks
PC_ASSERT(Header); PC_ASSERT(Header);
PC_ASSERT(Mdl); PC_ASSERT(Mdl);
@ -181,17 +178,17 @@ CIrpQueue::AddMapping(
Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
if (!Header->Data) if (!Header->Data)
{ {
// insufficient resources // insufficient resources
ExFreePool(Irp->AssociatedIrp.SystemBuffer); ExFreePool(Irp->AssociatedIrp.SystemBuffer);
Irp->AssociatedIrp.SystemBuffer = NULL; Irp->AssociatedIrp.SystemBuffer = NULL;
// complete and forget request // complete and forget request
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
// increment num mappings // increment num mappings
InterlockedIncrement(&m_NumMappings); InterlockedIncrement(&m_NumMappings);
@ -207,10 +204,10 @@ CIrpQueue::AddMapping(
// move to next mdl // move to next mdl
Mdl = Mdl->Next; Mdl = Mdl->Next;
} }
DPRINT("StreamHeaders %u NumData %u FrameSize %u NumDataAvailable %u\n", NumHeaders, NumData, m_MaxFrameSize, m_NumDataAvailable); DPRINT("StreamHeaders %u NumData %u FrameSize %u NumDataAvailable %u\n", NumHeaders, NumData, m_MaxFrameSize, m_NumDataAvailable);
*Data = NumData;
// mark irp as pending // mark irp as pending
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
@ -330,7 +327,7 @@ CIrpQueue::UpdateMapping(
if (m_CurrentOffset >= Size) if (m_CurrentOffset >= Size)
{ {
if (STREAMHEADER_INDEX(m_Irp) + 1 < STREAMHEADER_COUNT(m_Irp)) if (STREAMHEADER_INDEX(m_Irp) + 1 < STREAMHEADER_COUNT(m_Irp))
{ {
// the irp has at least one more stream header // the irp has at least one more stream header
m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(STREAMHEADER_INDEX(m_Irp) + 1); m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(STREAMHEADER_INDEX(m_Irp) + 1);
@ -345,7 +342,7 @@ CIrpQueue::UpdateMapping(
// done // done
return; return;
} }
// irp has been processed completly // irp has been processed completly
@ -354,7 +351,7 @@ CIrpQueue::UpdateMapping(
// loop all stream headers // loop all stream headers
for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++) for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++)
{ {
PC_ASSERT(StreamHeader); PC_ASSERT(StreamHeader);
// add size of buffer // add size of buffer
@ -369,20 +366,30 @@ CIrpQueue::UpdateMapping(
// get next stream header // get next stream header
StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
} }
if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
{
// looped streaming repeat the buffers untill
// the caller decides to stop the streams
// reset stream header index
m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0);
// re-insert irp
KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL);
// clear current irp
m_Irp = NULL;
// reset offset
m_CurrentOffset = 0;
// increment available data
InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, NumData);
// done
return;
}
m_Irp->IoStatus.Status = STATUS_SUCCESS; m_Irp->IoStatus.Status = STATUS_SUCCESS;
m_Irp->IoStatus.Information = NumData; m_Irp->IoStatus.Information = NumData;
#if 0
PC_ASSERT_IRQL(DISPATCH_LEVEL);
MmUnlockPages(m_Irp->MdlAddress);
IoFreeMdl(m_Irp->MdlAddress);
m_Irp->MdlAddress = NULL;
ExFreePool(m_Irp->AssociatedIrp.SystemBuffer);
m_Irp->AssociatedIrp.SystemBuffer = NULL;
#endif
// complete the request // complete the request
IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT); IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
// remove irp as it is complete // remove irp as it is complete

View file

@ -59,7 +59,7 @@ protected:
PMINIPORTWAVECYCLICSTREAM m_Stream; PMINIPORTWAVECYCLICSTREAM m_Stream;
KSSTATE m_State; KSSTATE m_State;
PKSDATAFORMAT m_Format; PKSDATAFORMAT m_Format;
KSPIN_CONNECT * m_ConnectDetails; PKSPIN_CONNECT m_ConnectDetails;
PVOID m_CommonBuffer; PVOID m_CommonBuffer;
ULONG m_CommonBufferSize; ULONG m_CommonBufferSize;
@ -187,6 +187,7 @@ PinWaveCyclicAudioPosition(
{ {
CPortPinWaveCyclic *Pin; CPortPinWaveCyclic *Pin;
PSUBDEVICE_DESCRIPTOR Descriptor; PSUBDEVICE_DESCRIPTOR Descriptor;
PKSAUDIO_POSITION Position;
// get sub device descriptor // get sub device descriptor
Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
@ -206,9 +207,21 @@ PinWaveCyclicAudioPosition(
{ {
// FIXME non multithreading-safe // FIXME non multithreading-safe
// copy audio position // copy audio position
RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset); Position = (PKSAUDIO_POSITION)Data;
if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING)
{
RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
}
else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
{
Position->PlayOffset = Pin->m_Position.PlayOffset % Pin->m_Position.WriteOffset;
Position->WriteOffset = Pin->m_IrpQueue->NumData();
}
Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION); Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -584,25 +597,21 @@ CPortPinWaveCyclic::HandleKsStream(
IN PIRP Irp) IN PIRP Irp)
{ {
NTSTATUS Status; NTSTATUS Status;
ULONG Data = 0;
InterlockedIncrement((PLONG)&m_TotalPackets); InterlockedIncrement((PLONG)&m_TotalPackets);
DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData()); DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
Status = m_IrpQueue->AddMapping(NULL, 0, Irp); Status = m_IrpQueue->AddMapping(Irp, &Data);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
PKSSTREAM_HEADER Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
PC_ASSERT(Header);
if (m_Capture) if (m_Capture)
m_Position.WriteOffset += Header->FrameExtent; m_Position.WriteOffset += Data;
else else
m_Position.WriteOffset += Header->DataUsed; m_Position.WriteOffset += Data;
return STATUS_PENDING; return STATUS_PENDING;
} }
return Status; return Status;

View file

@ -665,22 +665,19 @@ CPortPinWavePci::HandleKsStream(
IN PIRP Irp) IN PIRP Irp)
{ {
NTSTATUS Status; NTSTATUS Status;
ULONG Data = 0;
InterlockedIncrement((PLONG)&m_TotalPackets); InterlockedIncrement((PLONG)&m_TotalPackets);
DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData()); DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
Status = m_IrpQueue->AddMapping(NULL, 0, Irp); Status = m_IrpQueue->AddMapping(Irp, &Data);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
PKSSTREAM_HEADER Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
PC_ASSERT(Header);
if (m_Capture) if (m_Capture)
m_Position.WriteOffset += Header->FrameExtent; m_Position.WriteOffset += Data;
else else
m_Position.WriteOffset += Header->DataUsed; m_Position.WriteOffset += Data;
return STATUS_PENDING; return STATUS_PENDING;
} }

View file

@ -8,6 +8,22 @@
#include "private.hpp" #include "private.hpp"
KSPIN_INTERFACE PinInterfaces[] =
{
{
{STATIC_KSINTERFACESETID_Standard},
KSINTERFACE_STANDARD_STREAMING,
0
},
{
{STATIC_KSINTERFACESETID_Standard},
KSINTERFACE_STANDARD_LOOPED_STREAMING,
0
}
};
NTSTATUS NTSTATUS
NTAPI NTAPI
KsoDispatchCreateWithGenericFactory( KsoDispatchCreateWithGenericFactory(
@ -450,6 +466,9 @@ PcCreateSubdeviceDescriptor(
{ {
RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR)); RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
Descriptor->Factory.KsPinDescriptor[Index].Interfaces = PinInterfaces;
Descriptor->Factory.KsPinDescriptor[Index].InterfacesCount = sizeof(PinInterfaces) / sizeof(KSPIN_INTERFACE);
DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount); DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount);
Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0; Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;