mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 18:52:57 +00:00
[AUDIO-BRINGUP]
- Implement a timeout handler, which detects whether the audio thread has hung. The code has not yet been activated - Remove unused members svn path=/branches/audio-bringup/; revision=50001
This commit is contained in:
parent
f93d9928e3
commit
30d346530e
2 changed files with 189 additions and 61 deletions
|
@ -48,6 +48,7 @@ protected:
|
|||
friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
|
||||
friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
|
||||
friend VOID CALLBACK PinSetStateWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
||||
friend VOID NTAPI PinWaveCyclicIoTimerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
||||
|
||||
IPortWaveCyclic * m_Port;
|
||||
IPortFilterWaveCyclic * m_Filter;
|
||||
|
@ -69,8 +70,7 @@ protected:
|
|||
ULONG m_FrameSize;
|
||||
BOOL m_Capture;
|
||||
|
||||
ULONG m_TotalPackets;
|
||||
ULONG m_StopCount;
|
||||
ULONGLONG m_TotalPackets;
|
||||
KSAUDIO_POSITION m_Position;
|
||||
KSALLOCATOR_FRAMING m_AllocatorFraming;
|
||||
PSUBDEVICE_DESCRIPTOR m_Descriptor;
|
||||
|
@ -82,6 +82,12 @@ protected:
|
|||
|
||||
ULONG m_Delay;
|
||||
|
||||
ULONGLONG m_GlitchCount;
|
||||
ULONGLONG m_GlitchLength;
|
||||
|
||||
LARGE_INTEGER m_LastPacketTime;
|
||||
BOOLEAN m_Started;
|
||||
|
||||
LONG m_Ref;
|
||||
};
|
||||
|
||||
|
@ -106,7 +112,7 @@ NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Reque
|
|||
NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
|
||||
NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
|
||||
NTSTATUS NTAPI PinWaveCyclicDRMHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
|
||||
|
||||
VOID NTAPI PinWaveCyclicIoTimerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
||||
|
||||
DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
|
||||
DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
|
||||
|
@ -175,6 +181,7 @@ KSEVENT_SET PinWaveCyclicEventSet[] =
|
|||
|
||||
//==================================================================================================================================
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CPortPinWaveCyclic::QueryInterface(
|
||||
|
@ -201,6 +208,144 @@ CPortPinWaveCyclic::QueryInterface(
|
|||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CPortPinWaveCyclic *Pin;
|
||||
KSSTATE NewState;
|
||||
PIO_WORKITEM WorkItem;
|
||||
PIRP Irp;
|
||||
|
||||
}SETPIN_CONTEXT, *PSETPIN_CONTEXT;
|
||||
|
||||
VOID
|
||||
CALLBACK
|
||||
PinSetStateWorkerRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context;
|
||||
NTSTATUS Status;
|
||||
|
||||
// try set stream
|
||||
Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState);
|
||||
|
||||
DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
// store new state
|
||||
PinWorkContext->Pin->m_State = PinWorkContext->NewState;
|
||||
|
||||
if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
|
||||
{
|
||||
/* FIXME complete pending irps with successfull state */
|
||||
PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
|
||||
PinWorkContext->Pin->m_Stream->Silence(PinWorkContext->Pin->m_CommonBuffer, PinWorkContext->Pin->m_CommonBufferSize);
|
||||
PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
|
||||
PinWorkContext->Pin->m_Position.PlayOffset = 0;
|
||||
PinWorkContext->Pin->m_Position.WriteOffset = 0;
|
||||
PinWorkContext->Pin->m_GlitchCount = 0;
|
||||
PinWorkContext->Pin->m_GlitchLength = 0;
|
||||
|
||||
// unregister the time out
|
||||
PcUnregisterIoTimeout(GetDeviceObject(PinWorkContext->Pin->m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)PinWorkContext->Pin);
|
||||
}
|
||||
else if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
|
||||
{
|
||||
/* FIXME complete pending irps with successfull state */
|
||||
PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
|
||||
PinWorkContext->Pin->m_Stream->Silence(PinWorkContext->Pin->m_CommonBuffer, PinWorkContext->Pin->m_CommonBufferSize);
|
||||
PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
|
||||
PinWorkContext->Pin->m_Position.PlayOffset = 0;
|
||||
PinWorkContext->Pin->m_Position.WriteOffset = 0;
|
||||
PinWorkContext->Pin->m_GlitchCount = 0;
|
||||
PinWorkContext->Pin->m_GlitchLength = 0;
|
||||
|
||||
// unregister the time out
|
||||
PcUnregisterIoTimeout(GetDeviceObject(PinWorkContext->Pin->m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)PinWorkContext->Pin);
|
||||
}
|
||||
}
|
||||
|
||||
// store result
|
||||
if (PinWorkContext->Irp)
|
||||
{
|
||||
PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE);
|
||||
PinWorkContext->Irp->IoStatus.Status = Status;
|
||||
|
||||
// complete irp
|
||||
IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
// free work item
|
||||
IoFreeWorkItem(PinWorkContext->WorkItem);
|
||||
|
||||
// free work context
|
||||
FreeItem(PinWorkContext, TAG_PORTCLASS);
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PinWaveCyclicIoTimerRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PVOID Context)
|
||||
{
|
||||
CPortPinWaveCyclic *Pin;
|
||||
//PSETPIN_CONTEXT Ctx;
|
||||
LARGE_INTEGER CurrentTime;
|
||||
|
||||
// cast to pin impl
|
||||
Pin = (CPortPinWaveCyclic*)Context;
|
||||
|
||||
/* query system time */
|
||||
KeQuerySystemTime(&CurrentTime);
|
||||
|
||||
/* check if the connection matches */
|
||||
if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING && Pin->m_ResetState == KSRESET_END && Pin->m_State != KSSTATE_STOP && Pin->m_Started)
|
||||
{
|
||||
LARGE_INTEGER Diff;
|
||||
|
||||
Diff.QuadPart = CurrentTime.QuadPart - Pin->m_LastPacketTime.QuadPart;
|
||||
|
||||
if (Diff.QuadPart >= Int32x32To64(3000, 10000))
|
||||
{
|
||||
DPRINT1("AudioThread Hang detected: Last Packet %I64u CurrentTime %I64u Diff %I64u\n", Pin->m_LastPacketTime.QuadPart, CurrentTime.QuadPart, Diff.QuadPart);
|
||||
#if 0
|
||||
/* allocate pin context */
|
||||
Ctx = (PSETPIN_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETPIN_CONTEXT), TAG_PORTCLASS);
|
||||
|
||||
if (!Ctx)
|
||||
{
|
||||
/* no memory */
|
||||
return;
|
||||
}
|
||||
|
||||
/* initialize ctx */
|
||||
Ctx->Pin = Pin;
|
||||
if (Pin->m_State == KSSTATE_RUN)
|
||||
Ctx->NewState = KSSTATE_PAUSE;
|
||||
else if (Pin->m_State == KSSTATE_PAUSE)
|
||||
Ctx->NewState = KSSTATE_ACQUIRE;
|
||||
else if (Pin->m_State == KSSTATE_ACQUIRE)
|
||||
Ctx->NewState = KSSTATE_STOP;
|
||||
|
||||
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||
Ctx->Irp = NULL;
|
||||
|
||||
if (!Ctx->WorkItem)
|
||||
{
|
||||
/* no memory */
|
||||
FreeItem(Ctx, TAG_PORTCLASS);
|
||||
return;
|
||||
}
|
||||
|
||||
/* queue the work item */
|
||||
IoQueueWorkItem(Ctx->WorkItem, PinSetStateWorkerRoutine, DelayedWorkQueue, (PVOID)Ctx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PinWaveCyclicDRMHandler(
|
||||
|
@ -360,13 +505,13 @@ PinWaveCyclicAudioPosition(
|
|||
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);
|
||||
DPRINT("Play %I64u Record %I64u\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;
|
||||
Position->WriteOffset = (ULONGLONG)Pin->m_IrpQueue->GetCurrentIrpOffset();
|
||||
DPRINT("Play %lu Write %lu\n", Position->PlayOffset, Position->WriteOffset);
|
||||
DPRINT("Play %I64u Write %I64u\n", Position->PlayOffset, Position->WriteOffset);
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
|
||||
|
@ -377,58 +522,6 @@ PinWaveCyclicAudioPosition(
|
|||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CPortPinWaveCyclic *Pin;
|
||||
KSSTATE NewState;
|
||||
PIO_WORKITEM WorkItem;
|
||||
PIRP Irp;
|
||||
|
||||
}SETPIN_CONTEXT, *PSETPIN_CONTEXT;
|
||||
|
||||
VOID
|
||||
CALLBACK
|
||||
PinSetStateWorkerRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context;
|
||||
NTSTATUS Status;
|
||||
|
||||
// try set stream
|
||||
Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState);
|
||||
|
||||
DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
// store new state
|
||||
PinWorkContext->Pin->m_State = PinWorkContext->NewState;
|
||||
|
||||
if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
|
||||
{
|
||||
/* FIXME complete pending irps with successfull state */
|
||||
PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
|
||||
}
|
||||
//HACK
|
||||
//PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
|
||||
}
|
||||
|
||||
// store result
|
||||
PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE);
|
||||
PinWorkContext->Irp->IoStatus.Status = Status;
|
||||
|
||||
// complete irp
|
||||
IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT);
|
||||
|
||||
// free work item
|
||||
IoFreeWorkItem(PinWorkContext->WorkItem);
|
||||
|
||||
// free work context
|
||||
FreeItem(PinWorkContext, TAG_PORTCLASS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PinWaveCyclicState(
|
||||
|
@ -470,20 +563,46 @@ PinWaveCyclicState(
|
|||
{
|
||||
// FIXME
|
||||
// complete with successful state
|
||||
DPRINT1("BytesPlayed %I64u, GlitchCount %I64u GlitchLength %I64u\n", Pin->m_Position.PlayOffset, Pin->m_GlitchCount, Pin->m_GlitchLength);
|
||||
Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
|
||||
Pin->m_IrpQueue->CancelBuffers();
|
||||
Pin->m_Position.PlayOffset = 0;
|
||||
Pin->m_Position.WriteOffset = 0;
|
||||
Pin->m_GlitchCount = 0;
|
||||
Pin->m_GlitchLength = 0;
|
||||
|
||||
|
||||
// unregister the time out
|
||||
PcUnregisterIoTimeout(GetDeviceObject(Pin->m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)Pin);
|
||||
}
|
||||
else if (Pin->m_State == KSSTATE_STOP)
|
||||
{
|
||||
DPRINT1("BytesPlayed %I64u, GlitchCount %I64u GlitchLength %I64u\n", Pin->m_Position.PlayOffset, Pin->m_GlitchCount, Pin->m_GlitchLength);
|
||||
Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
|
||||
Pin->m_IrpQueue->CancelBuffers();
|
||||
Pin->m_Position.PlayOffset = 0;
|
||||
Pin->m_Position.WriteOffset = 0;
|
||||
Pin->m_GlitchCount = 0;
|
||||
Pin->m_GlitchLength = 0;
|
||||
|
||||
// unregister the time out
|
||||
PcUnregisterIoTimeout(GetDeviceObject(Pin->m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)Pin);
|
||||
}
|
||||
// store result
|
||||
Irp->IoStatus.Information = sizeof(KSSTATE);
|
||||
|
||||
if (*State == KSSTATE_RUN)
|
||||
{
|
||||
// register wave hung routine
|
||||
NTSTATUS PcStatus = PcRegisterIoTimeout(GetDeviceObject(Pin->m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)Pin);
|
||||
if (!NT_SUCCESS(PcStatus))
|
||||
{
|
||||
DPRINT1("Failed to register timer routine with %x\n", PcStatus);
|
||||
}
|
||||
|
||||
// set flag that stream has started for the wave hung routine
|
||||
Pin->m_Started = TRUE;
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
@ -701,8 +820,10 @@ CPortPinWaveCyclic::UpdateCommonBuffer(
|
|||
Gap = Position - m_CommonBufferOffset;
|
||||
if (Gap > BufferLength)
|
||||
{
|
||||
// increment glitchcount
|
||||
m_GlitchCount++;
|
||||
m_GlitchLength += BufferLength;
|
||||
// insert silence samples
|
||||
DPRINT1("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength);
|
||||
m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
|
||||
|
||||
m_CommonBufferOffset += BufferLength;
|
||||
|
@ -760,8 +881,11 @@ CPortPinWaveCyclic::UpdateCommonBufferOverlap(
|
|||
Gap = m_CommonBufferSize - m_CommonBufferOffset + Position;
|
||||
if (Gap > BufferLength)
|
||||
{
|
||||
// increment glitchcount
|
||||
m_GlitchCount++;
|
||||
m_GlitchLength += BufferLength;
|
||||
|
||||
// insert silence samples
|
||||
DPRINT1("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position);
|
||||
m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
|
||||
|
||||
m_CommonBufferOffset += BufferLength;
|
||||
|
@ -933,6 +1057,8 @@ CPortPinWaveCyclic::DeviceIoControl(
|
|||
{
|
||||
m_Position.WriteOffset += Data;
|
||||
Status = STATUS_PENDING;
|
||||
/* time stamp last packet */
|
||||
KeQuerySystemTime(&m_LastPacketTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1034,6 +1160,9 @@ CPortPinWaveCyclic::Close(
|
|||
DPRINT("Warning: failed to stop stream with %x\n", Status);
|
||||
PC_ASSERT(0);
|
||||
}
|
||||
|
||||
// unregister the time out
|
||||
PcUnregisterIoTimeout(GetDeviceObject(m_Port), PinWaveCyclicIoTimerRoutine, (PVOID)this);
|
||||
}
|
||||
// set state to stop
|
||||
m_State = KSSTATE_STOP;
|
||||
|
@ -1269,7 +1398,7 @@ CPortPinWaveCyclic::Init(
|
|||
Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Failed to add pin to service group\n");
|
||||
DPRINT1("Failed to add pin to service group\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,6 @@ protected:
|
|||
|
||||
ULONG m_TotalPackets;
|
||||
KSAUDIO_POSITION m_Position;
|
||||
ULONG m_StopCount;
|
||||
|
||||
BOOL m_bUsePrefetch;
|
||||
ULONG m_PrefetchOffset;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue