|
|
//
// Differnt level of WDM supports may use different API
//
// e.g. MmGetSystemAddressForMdl (win9x)
// Return NULL for Win9x; bugcheck for Win2000 if NULL would have returned.
//
// MmGetSystemAddressForMdlSafe (win2000)
// Not supported in Win9x or Millen
//
// This is defined in SOURCES file.
#define NUM_BUF_ATTACHED_THEN_ISOCH 4 // number of buffers attached before streaming and also as the water mark.
//
// These definition and macros are used to calculate the picture numbers.
// With OHCI spec, the data is returned with the 16bit Cycle time, which includes
// 3 bits of SecondCount and 13 bits of the CycleCount. This "timer" will wrap in 8 seconds.
//
#define TIME_PER_CYCLE 1250 // One 1394 cycle; unit = 100 nsec
#define CYCLES_PER_SECOND 8000
#define MAX_SECOND_COUNTS 7 // The returned CycleTime contains 3 bits of SecondCount; that is 0..7
#define MAX_CYCLES (MAX_SECOND_COUNTS + 1) * CYCLES_PER_SECOND // 0..MAX_CYCLES-1
#define MAX_CYCLES_TIME (MAX_CYCLES * TIME_PER_CYCLE) // unit = 100nsec
#define VALIDATE_CYCLE_COUNTS(CT) ASSERT(CT.CL_SecondCount <= 7 && CT.CL_CycleCount < CYCLES_PER_SECOND && CT.CL_CycleOffset == 0);
#define CALCULATE_CYCLE_COUNTS(CT) (CT.CL_SecondCount * CYCLES_PER_SECOND + CT.CL_CycleCount);
#define CALCULATE_DELTA_CYCLE_COUNT(prev, now) ((now > prev) ? now - prev : now + MAX_CYCLES - prev)
//
// Return avg time per frame in the unit of 100 nsec;
// for calculation accuracy using only integer calculation,
// we should do do multimplcation before division.
// That is why the application can request to get numerator and denominator separately.
//
#define GET_AVG_TIME_PER_FRAME(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? (1001000/3) : FRAME_TIME_PAL)
#define GET_AVG_TIME_PER_FRAME_NUM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 1001000 : 400000)
#define GET_AVG_TIME_PER_FRAME_DENOM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 3 : 1)
#define GET_NUM_PACKETS_PER_FRAME(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 4004/15 /* 100100/375 */ : MAX_SRC_PACKETS_PER_PAL_FRAME)
#define GET_NUM_PACKETS_PER_FRAME_NUM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 4004 : MAX_SRC_PACKETS_PER_PAL_FRAME)
#define GET_NUM_PACKETS_PER_FRAME_DENOM(format) ((format == AVCSTRM_FORMAT_SDDV_NTSC) ? 15 : 1)
//
// Structure used to keep track of and to perform stream data queuing
//
typedef struct _AVC_STREAM_DATA_STRUCT {
ULONG SizeOfThisPacket;
//
// Frame size is calculated based on
// CIP_DBS * 4 * (CIP_FN==0? 1 : (CIP_FN==1 ? 2 : (CIP_FN==2 ? 4 : 8)))
//
ULONG SourcePacketSize;
//
// Frame size is calculated based on
// SourcePacketSize * SRC_PACKETS_PER_***
//
ULONG FrameSize;
//
// Current stream time
//
LONGLONG CurrentStreamTime; ULONG LastCycleCount; // Used only for MPEG2TS stream
//
// Statistic of the frame information since last start stream
// PictureNumber = FramesProcessed + FramesDropped + cndSRBCancelled.
//
LONGLONG PictureNumber; LONGLONG FramesProcessed; // Frame made it to 1394 serial bus.
LONGLONG FramesDropped;
#if DBG
LONGLONG FramesAttached; #endif
LONGLONG cntFrameCancelled;
//
// Count number of Data IRP received
//
LONGLONG cntDataReceived;
//
// Count and list for the attach list
//
LONG cntDataAttached; LIST_ENTRY DataAttachedListHead;
//
// Count and list for the SRB list
//
LONG cntDataQueued; // Used only with SRB_WRITE_DATA
LIST_ENTRY DataQueuedListHead; // Used only with SRB_WRITE_DATA
//
// Count and list for the detach list
//
LONG cntDataDetached; LIST_ENTRY DataDetachedListHead;
//
// Lock to serialize attach and detach of list
//
KSPIN_LOCK DataListLock;
//
// Memory blocked allocated at passive level for queuing data IOs.
//
PBYTE pMemoryBlock;
//
// Signalled when there is no more attach frame; mainoy used to guarantee that all
// data attached are transmitted before isoch is stopped for transmitting data
// from PC to AVC device.
//
KEVENT hNoAttachEvent;
} AVC_STREAM_DATA_STRUCT, * PAVC_STREAM_DATA_STRUCT;
typedef struct DEVICE_EXTENSION;
//
// An AVC stream extension is created per stream opened. This will be returned to the caller,
// when it will be used as the context (like a HANDLE) for subsequent call.
// The allocation will include
//
// AVC_STREAM_EXTENSION
// AV1394_FORMAT_INFO
// AV_CLIENT_REQ
//
typedef struct _AVC_STREAM_EXTENSION {
ULONG SizeOfThisPacket;
//
// This driver's device extension
//
struct DEVICE_EXTENSION * pDevExt;
//
// Data flow direction
//
KSPIN_DATAFLOW DataFlow; // Determine in or output pin
//
// Holds state
//
KSSTATE StreamState;
//
// This flag indicate if isoch is TALK/LISTEN or STOPPED
//
BOOLEAN IsochIsActive; // Close associated with StreamState
//
// Abstrction i/oPCR of an AVC device and PC itself as a plug handles
// Connection handle is used when two plugs are connected.
//
HANDLE hPlugRemote; // Target (DVCR,D-VHS) device plug;
HANDLE hPlugLocal; //.Local i/oPCR;
HANDLE hConnect; // Connect two plugs
//
// Structure for specifing an AVC stream
//
PAVCSTRM_FORMAT_INFO pAVCStrmFormatInfo;
//
// Structure for data flow control (IsochActive, IOQueues..etc)
//
PAVC_STREAM_DATA_STRUCT pAVCStrmDataStruc;
//
// Synchronizing setting stream control and processing data
//
KMUTEX hMutexControl;
//
// Synchronize sharing the below AV_61883_REQUEST structure
// Since all the stream control are synchronouse so we can use the same
// AV61883Req structure to issue 61883 request
//
KMUTEX hMutexAVReq; PIRP pIrpAVReq; AV_61883_REQUEST AVReq;
//
// Counter used to indicate starting of an work item to cancel
//
LONG lAbortToken;
//
// Hold the work item
//
#ifdef USE_WDM110 // Win2000 code base
PIO_WORKITEM pIoWorkItem; #else
WORK_QUEUE_ITEM IoWorkItem; #endif
//
// TO signal that an work item is completed.
//
KEVENT hAbortDoneEvent;
//
// Cached plug state (these are dynamic values)
//
CMP_GET_PLUG_STATE RemotePlugState;
#ifdef NT51_61883
//
// Cyclic cycle count of last DV frame
//
ULONG CycleCount16bits; #endif // NT51_61883
//
// Keep track of the last system time when the stream time was updated.
// This is used to calibrate the current stream time when it is queries.
//
ULONGLONG LastSystemTime;
//
// Discontinuity is introduced when traistioning from RUN->PAUSE->RUN.
// The stream time will not increment in PAUSE state but system time (1394 CycleTime) does.
//
BOOL b1stNewFrameFromPauseState;
} AVC_STREAM_EXTENSION, *PAVC_STREAM_EXTENSION;
//
// Valid data entry states for a data request and they
// can be Or'ed to show their code path.
//
// Examples of different possible code path:
//
// (A) Attached -> Pending -> Callback -> Completed
// (B) Callback -> Attached -> Completed
// (C) Attached -> Cancelled -> Completed
//
enum DATA_ENTRY_STATE { DE_PREPARED = 0x01, DE_IRP_LOWER_ATTACHED_COMPLETED = 0x02, DE_IRP_UPPER_PENDING_COMPLETED = 0x04, DE_IRP_LOWER_CALLBACK_COMPLETED = 0x08, DE_IRP_UPPER_COMPLETED = 0x10, DE_IRP_ERROR = 0x20, DE_IRP_CANCELLED = 0x40, };
#define IsStateSet(state, bitmask) ((state & (bitmask)) == bitmask)
//
// This is the data entry used to attach a frame
//
typedef struct _AVCSTRM_DATA_ENTRY {
LIST_ENTRY ListEntry;
//
// Keep track of data entry state
//
enum DATA_ENTRY_STATE State;
//
// IRP from client of upper layer
//
PIRP pIrpUpper;
//
// Clock provider information
//
BOOL ClockProvider; // Client is a clock provider?
HANDLE ClockHandle; // This is used only if !ClockProvider; it is possible that there is no clock used.
//
// Contain information about this streaming buffer
//
PKSSTREAM_HEADER StreamHeader;
//
// Frame buffer
//
PVOID FrameBuffer;
//
// Stream extension (Context) of the stream of this frame
//
PAVC_STREAM_EXTENSION pAVCStrmExt; #if DBG
//
// Add debug related info here
//
LONGLONG FrameNumber; #endif
//
// 61883 CIP frame structure
//
struct _CIP_FRAME * Frame;
//
// IRP used to send to 61883 (lower layer) for AV request, such as attach and release
//
PIRP pIrpLower;
//
// Use to send 61883 AV data request
//
AV_61883_REQUEST AVReq;
} AVCSTRM_DATA_ENTRY, *PAVCSTRM_DATA_ENTRY;
//
// To open a stream.
// A context is created and return to the caller. This context is need for all
// stream operation.
//
NTSTATUS AVCStreamOpen( IN PIRP pIrp, // The Irp from its client
IN struct DEVICE_EXTENSION * pDevExt, IN OUT AVCSTRM_OPEN_STRUCT * pOpenStruct );
// To Close a stram.
NTSTATUS AVCStreamClose( IN PIRP pIrp, // The Irp from its client
IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt );
//
// Process stream control
//
NTSTATUS AVCStreamControlGetState( IN PIRP pIrp, // The Irp from its client
IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, OUT KSSTATE * pKSState ); NTSTATUS AVCStreamControlSetState( IN PIRP pIrp, // The Irp from its client
IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN KSSTATE KSState );
NTSTATUS AVCStreamControlGetProperty( IN PIRP pIrp, // The Irp from its client
IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN PSTREAM_PROPERTY_DESCRIPTOR pSPD // BUGBUG StreamClass specific
); NTSTATUS AVCStreamControlSetProperty( IN PIRP pIrp, // The Irp from its client
IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN PSTREAM_PROPERTY_DESCRIPTOR pSPD // BUGBUG StreamClass specific
);
// Process SRB_READ/WRITE_DATA; this is the only IRPs that will operate asychronously
// with. and STATUS_PENDING is returned.
NTSTATUS AVCStreamRead( IN PIRP pIrpUpper, IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN AVCSTRM_BUFFER_STRUCT * pBufferStruct );
NTSTATUS AVCStreamWrite( IN PIRP pIrpUpper, IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN AVCSTRM_BUFFER_STRUCT * pBufferStruct );
/*
This will stop streaming and cancel all pending data irps. This is typically used to cancel all Irps. To cancel a single Irp, use IoCancelIrp(). */ NTSTATUS AVCStreamAbortStreaming( IN PIRP pIrp, // The Irp from its client
IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt );
/*
Process surprise removal of a device */ NTSTATUS AVCStreamSurpriseRemoval( IN struct DEVICE_EXTENSION * pDevExt );
////////////////////////////////
// AvcUtil.c function prototypes
////////////////////////////////
ULONGLONG GetSystemTime( ) ;
NTSTATUS AVCStrmAttachFrameCR( IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp, IN PAVCSTRM_DATA_ENTRY pDataEntry );
VOID AVCStrmFormatAttachFrame( IN KSPIN_DATAFLOW DataFlow, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN AVCSTRM_FORMAT AVCStrmFormat, IN PAV_61883_REQUEST pAVReq, IN PAVCSTRM_DATA_ENTRY pDataEntry, IN ULONG ulSourcePacketSize, // Packet length in bytes
IN ULONG ulFrameSize, // Buffer size; may contain one or multiple source packets
IN PIRP pIrpUpper, IN PKSSTREAM_HEADER StreamHeader, IN PVOID FrameBuffer );
NTSTATUS AVCStrmGetPlugHandle( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt );
NTSTATUS AVCStrmGetPlugState( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt );
NTSTATUS AVCStrmGetConnectionProperty( IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, PSTREAM_PROPERTY_DESCRIPTOR pSPD, PULONG pulActualBytesTransferred );
NTSTATUS AVCStrmGetDroppedFramesProperty( IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, PSTREAM_PROPERTY_DESCRIPTOR pSPD, PULONG pulBytesTransferred );
NTSTATUS AVCStrmMakeConnection( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt );
NTSTATUS AVCStrmBreakConnection( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt );
NTSTATUS AVCStrmStartIsoch( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmStopIsoch( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt ); VOID AVCStrmWaitUntilAttachedAreCompleted( IN PAVC_STREAM_EXTENSION pAVCStrmExt ); NTSTATUS AVCStrmAllocateQueues( IN struct DEVICE_EXTENSION * pDevExt, IN PAVC_STREAM_EXTENSION pAVCStrmExt, IN KSPIN_DATAFLOW DataFlow, IN PAVC_STREAM_DATA_STRUCT pDataStruc, PAVCSTRM_FORMAT_INFO pAVCStrmFormatInfo ); NTSTATUS AVCStrmFreeQueues( IN PAVC_STREAM_DATA_STRUCT pDataStruc );
NTSTATUS AVCStrmCancelIO( IN PDEVICE_OBJECT DeviceObject, IN PAVC_STREAM_EXTENSION pAVCStrmExt );
NTSTATUS AVCStrmValidateFormat( PAVCSTRM_FORMAT_INFO pAVCFormatInfo );
void AVCStrmAbortStreamingWorkItemRoutine( #ifdef USE_WDM110 // Win2000 code base
// Extra parameter if using WDM10
PDEVICE_OBJECT DeviceObject, #endif
IN PAVC_STREAM_EXTENSION pAVCStrmExt );
|