void CHardwareSimulation:: FreeSGEntry( _In_ PLIST_ENTRY Entry, _In_ PCWSTR EventName, _In_opt_ LPCGUID Activity, _In_ ULONG DataUsed ) { PAGED_CODE(); PSCATTER_GATHER_ENTRY SGEntry = reinterpret_cast <PSCATTER_GATHER_ENTRY> ( CONTAINING_RECORD ( Entry, SCATTER_GATHER_ENTRY, ListEntry ) ); NT_ASSERT(SGEntry->CloneEntry); NT_ASSERT(SGEntry->CloneEntry->StreamHeader); SGEntry->CloneEntry->StreamHeader->DataUsed = DataUsed; KsStreamPointerDelete(SGEntry->CloneEntry); // // Release the scatter / gather entry back to our lookaside. // ExFreeToNPagedLookasideList ( &m_ScatterGatherLookaside, SGEntry ); }
NTSTATUS CEncoderPin:: CleanupReferences ( ) /*++ Routine Description: Clean up any references we're holding on frames after we abruptly stop the hardware. Arguments: None Return Value: Success / Failure --*/ { PAGED_CODE(); PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin); PKSSTREAM_POINTER NextClone = NULL; // // Walk through the clones, deleting them, and setting DataUsed to // zero since we didn't use any data! // while (Clone) { NextClone = KsStreamPointerGetNextClone (Clone); Clone -> StreamHeader -> DataUsed = 0; KsStreamPointerDelete (Clone); Clone = NextClone; } return STATUS_SUCCESS; }
void CEncoderPin:: CompleteMappings ( IN ULONG NumMappings ) /*++ Routine Description: Called to notify the pin that a given number of scatter / gather mappings have completed. Let the buffers go if possible. We're called at DPC. Arguments: NumMappings - The number of mappings that have completed. Return Value: None --*/ { ULONG MappingsRemaining = NumMappings; // // Walk through the clones list and delete clones whose time has come. // The list is guaranteed to be kept in the order they were cloned. // PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin); while (MappingsRemaining && Clone) { PKSSTREAM_POINTER NextClone = KsStreamPointerGetNextClone (Clone); #if defined(_BUILD_SW_TUNER_ON_X64) #else // // Count up the number of bytes we've completed and mark this // in the Stream Header. In mapped queues // (KSPIN_FLAG_GENERATE_MAPPINGS), this is the responsibility of // the minidriver. In non-mapped queues, AVStream performs this. // ULONG MappingsToCount = (MappingsRemaining > Clone -> OffsetOut.Remaining) ? Clone -> OffsetOut.Remaining : MappingsRemaining; // // Update DataUsed according to the mappings. // for (ULONG CurMapping = 0; CurMapping < MappingsToCount; CurMapping++) { Clone -> StreamHeader -> DataUsed += Clone -> OffsetOut.Mappings [CurMapping].ByteCount; } #endif // // If we have completed all remaining mappings in this clone, it // is an indication that the clone is ready to be deleted and the // buffer released. Set anything required in the stream header which // has not yet been set. If we have a clock, we can timestamp the // sample. // #if defined(_BUILD_SW_TUNER_ON_X64) if (Clone -> StreamHeader -> DataUsed >= Clone -> OffsetOut.Remaining) { #else if (MappingsRemaining >= Clone -> OffsetOut.Remaining) { #endif Clone -> StreamHeader -> Duration = m_TransportInfo -> AvgTimePerFrame; Clone -> StreamHeader -> PresentationTime.Numerator = Clone -> StreamHeader -> PresentationTime.Denominator = 1; // // If a clock has been assigned, timestamp the packets with the // time shown on the clock. // if (m_Clock) { LONGLONG ClockTime = m_Clock -> GetTime (); Clone -> StreamHeader -> PresentationTime.Time = ClockTime; Clone -> StreamHeader -> OptionsFlags = KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID; } else { // // If there is no clock, don't time stamp the packets. // Clone -> StreamHeader -> PresentationTime.Time = 0; } // // If all of the mappings in this clone have been completed, // delete the clone. We've already updated DataUsed above. // #if defined(_BUILD_SW_TUNER_ON_X64) MappingsRemaining--; #else MappingsRemaining -= Clone -> OffsetOut.Remaining; #endif KsStreamPointerDelete (Clone); } else { // // If only part of the mappings in this clone have been completed, // update the pointers. Since we're guaranteed this won't advance // to a new frame by the check above, it won't fail. // #if defined(_BUILD_SW_TUNER_ON_X64) KsStreamPointerAdvanceOffsets ( Clone, 0, Clone -> StreamHeader -> DataUsed, FALSE ); #else KsStreamPointerAdvanceOffsets ( Clone, 0, MappingsRemaining, FALSE ); #endif MappingsRemaining = 0; } // // Go to the next clone. // Clone = NextClone; } // // If we've used all the mappings in hardware and pended, we can kick // processing to happen again if we've completed mappings. // if (m_PendIo) { m_PendIo = TRUE; KsPinAttemptProcessing (m_Pin, TRUE); } } /************************************************************************** DISPATCH AND DESCRIPTOR LAYOUT **************************************************************************/ // // This is the data range description of the capture output pin. // // MEDIASUBTYPE_None #define MEDIASUBTYPE_MPEG2_PROGRAM\ 0xe06d8022, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x05f, 0x6c, 0xbb, 0xea const KSDATARANGE FormatEncoderOut = { // insert the KSDATARANGE and KSDATAFORMAT here { sizeof( KSDATARANGE), // FormatSize 0, // Flags - (N/A) PS_SAMPLE_SIZE, // SampleSize 0, // Reserved { STATIC_KSDATAFORMAT_TYPE_STREAM }, // MajorFormat { MEDIASUBTYPE_MPEG2_PROGRAM}, // SubFormat { STATIC_KSDATAFORMAT_SPECIFIER_NONE } // Specifier } }; // // This is the data range description of the capture input pin. // const KS_DATARANGE_BDA_TRANSPORT FormatEncoderIn = { // insert the KSDATARANGE and KSDATAFORMAT here { sizeof( KS_DATARANGE_BDA_TRANSPORT), // FormatSize 0, // Flags - (N/A) 0, // SampleSize - (N/A) 0, // Reserved { STATIC_KSDATAFORMAT_TYPE_STREAM }, // MajorFormat { STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT }, // SubFormat { STATIC_KSDATAFORMAT_SPECIFIER_BDA_TRANSPORT } // Specifier }, // insert the BDA_TRANSPORT_INFO here { PS_PACKET_SIZE, // ulcbPhyiscalPacket PS_SAMPLE_SIZE, // ulcbPhyiscalFrame 0, // ulcbPhyiscalFrameAlignment (no requirement) 0 // AvgTimePerFrame (not known) } }; // // EncoderPinDispatch: // // This is the dispatch table for the capture pin. It provides notifications // about creation, closure, processing, data formats, etc... // extern const KSPIN_DISPATCH EncoderPinDispatch = { CEncoderPin::DispatchCreate, // Pin Create NULL, // Pin Close CEncoderPin::DispatchProcess, // Pin Process NULL, // Pin Reset NULL, // Pin Set Data Format CEncoderPin::DispatchSetState, // Pin Set Device State NULL, // Pin Connect NULL, // Pin Disconnect NULL, // Clock Dispatch NULL // Allocator Dispatch }; // // InputPinDispatch: // // This is the dispatch table for the capture pin. It provides notifications // about creation, closure, processing, data formats, etc... // extern const KSPIN_DISPATCH InputPinDispatch = { CEncoderPin::DispatchCreate, // Pin Create NULL, // Pin Close NULL, // Pin Process NULL, // Pin Reset NULL, // Pin Set Data Format NULL, // Pin Set Device State NULL, // Pin Connect NULL, // Pin Disconnect NULL, // Clock Dispatch NULL // Allocator Dispatch }; // // EncoderPinAllocatorFraming: // // This is the simple framing structure for the capture pin. Note that this // will be modified via KsEdit when the actual capture format is determined. // extern DECLARE_SIMPLE_FRAMING_EX ( EncoderPinAllocatorFraming, // FramingExName STATICGUIDOF (KSMEMORY_TYPE_KERNEL_NONPAGED), // MemoryType KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY, // Flags 8, // Frames 0, // Alignment PS_SAMPLE_SIZE, // MinFrameSize PS_SAMPLE_SIZE // MaxFrameSize ); // // EncoderOutPinDataRanges: // // This is the list of data ranges supported on the capture output pin. // extern const PKSDATARANGE EncoderOutPinDataRanges [ENCODER_OUT_PIN_DATA_RANGE_COUNT] = { (PKSDATARANGE) &FormatEncoderOut }; // // EncoderInPinDataRanges: // // This is the list of data ranges supported on the capture input pin. // extern const PKSDATARANGE EncoderInPinDataRanges [ENCODER_IN_PIN_DATA_RANGE_COUNT] = { (PKSDATARANGE) &FormatEncoderIn };