⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hwcappin.cpp

📁 2个avstream类型驱动演示
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// HwcapPin.cpp: implementation of the HwcapPin class.
//
//////////////////////////////////////////////////////////////////////

#include	<vdw.h>
#include	<kavstream.h>

#include "Hwcap.h"
#include "HwcapFormats.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

HwcapPin::HwcapPin() :
 KsPin(), 
	 m_VideoInfoHeader(0),  m_pHardware(NULL), m_bPending(FALSE), 
	 m_pClock(0)
{

}

HwcapPin::~HwcapPin()
{
	ASSERT(m_pHardware==NULL);
	delete m_pHardware;
	delete m_VideoInfoHeader;
	if (m_pClock) m_pClock->Release();
}



///////////////////////////////////////////////////////////////////////
// HwcapPin::OnCreate
//
// Parameters:
// 	I                    - IRP_MJ_CREATE 
// Returns:
// 	STATUS_SUCCESS or STATUS_PENDING
// Comments:
// 	See AVStrMiniPinCreate
NTSTATUS HwcapPin::OnCreate(KIrp I)
{
    NTSTATUS status;

	// Get KS objects:

	PKSPIN Pin		 = PKSPIN(*this);
	PKSFILTER Filter = KsPin::Parent();

	g_Trace << "HwcapPin::OnCreate, id=" << Pin->Id << EOL;

    //
    // Indicate the extended header size.
    //
    Pin->StreamHeaderSize = sizeof(KSSTREAM_HEADER) + sizeof(KS_FRAME_INFO);

	// cache the header info

	m_VideoInfoHeader = new (Pin) KsVideoInfoHeader;

	if (m_VideoInfoHeader==NULL)
		return STATUS_INSUFFICIENT_RESOURCES;

	// lock framing descriptor for editing

    if ((status = KsEdit(Pin, &Pin->Descriptor, 'deks')) == STATUS_SUCCESS) 
		if ((status = KsEdit(Pin, &Pin->Descriptor->AllocatorFraming, 'deks')) == STATUS_SUCCESS) {

        PKSALLOCATOR_FRAMING_EX framing = const_cast<PKSALLOCATOR_FRAMING_EX>(Pin->Descriptor->AllocatorFraming);

        framing->FramingItem[0].Frames = 2;
        framing->FramingItem[0].PhysicalRange.MinFrameSize = 
        framing->FramingItem[0].PhysicalRange.MaxFrameSize = 
        framing->FramingItem[0].FramingRange.Range.MinFrameSize = 
        framing->FramingItem[0].FramingRange.Range.MaxFrameSize = (*m_VideoInfoHeader)->bmiHeader.biSizeImage;
        framing->FramingItem[0].PhysicalRange.Stepping = 
        framing->FramingItem[0].FramingRange.Range.Stepping = 0;
	}
                    
    return status;
}


///////////////////////////////////////////////////////////////////////
// HwcapPin::OnSetDeviceState
//
// Parameters:
// 	From                 - The target KSSTATE after receipt of the IRP
// 	To                   - The previous KSSTATE
// Returns:
// 	STATUS_SUCCESS or the error code
// Comments:
// 	Pins that use the standard transport mechanism receive 
//  filtered (single step) state changes through the owning pipe through 
//  this routine.
//  Non-standard transports receive non-filtered (1+ step) state changes
//  through this routine. See AVStrMiniPinSetDeviceState
//
NTSTATUS HwcapPin::OnSetDeviceState(KSSTATE To, KSSTATE From)
{
	g_Trace << "HwcapPin::OnSetDeviceState, id=" << PKSPIN(*this)->Id 
		    << " from " << From << " to " << To << EOL;

    NTSTATUS  Status = STATUS_SUCCESS;

	// Get parent device object to access hardware

	HwcapDevice* device = reinterpret_cast<HwcapDevice*> (KsPin::GetDevice());

	ASSERT(device);
    
    switch (To) 
    {
        case KSSTATE_STOP:
			//
			// stop hardware, release clocks (if any) and release resources
			//
			if (m_pHardware) {
				if (m_pHardware->IsOn()) {
					m_pHardware->Stop();
					m_pHardware->WaitForStop();
				}

				device->m_HardwareResources.Release(m_pHardware);
				m_pHardware = NULL;
			}

			// Release clocks
			if (m_pClock) {
				m_pClock->Release();
				m_pClock = NULL;
			}

			DeleteClones();

            break;
            
        case KSSTATE_ACQUIRE:
            //
            // This is a KS only state, that has no correspondence in DirectShow
			// Acquire hardware resources at this point.
			// If successful, configure it, too
            // 

			if (From == KSSTATE_STOP) {
				ASSERT(m_pHardware==0);
				m_pHardware = device->m_HardwareResources.Acquire(*this);
				if (m_pHardware) {
					Status = m_pHardware->Configure(*m_VideoInfoHeader, this);
					ASSERT(NT_SUCCESS(Status));
					
				}
				else {
					ASSERT(!"KSSTATE_ACQUIRE");
					Status = STATUS_INSUFFICIENT_RESOURCES;
				}

				// Get clock interface
				m_pClock = KsPin::GetReferenceClock();
				if (m_pClock) {
					g_Trace.Trace(TraceInfo, "Assigned clocks %p\n", m_pClock);
				}

			} else {
				// this sample supports only ordered +/- transitions => XP only
				g_Trace << "Non standard state transition" << EOL;
			}


            break;
            
        case KSSTATE_PAUSE:
			// Pause toggles
			if (m_pHardware == NULL)
				break;
			if (From == KSSTATE_RUN) { 
				m_pHardware->Stop();
				m_pHardware->WaitForStop();
				break;
			}
            else; // fall through: pause toggles!
			//break;
            
        case KSSTATE_RUN:
			// start hardware simulation
			//
			ASSERT(m_pHardware);
			if (!m_pHardware->IsOn())
				m_pHardware->Start();
            break;
    }
    
	return Status;
}


///////////////////////////////////////////////////////////////////////
// HwcapPin::OnProcess
//
// Parameters:
//	none
// Returns:
// 	STATUS_SUCCESS to continue processing. Return STATUS_PENDING to stop 
//  processing until the next triggering 
// Comments:
// 	Called when new data arrives into a previously empty queue. Alternatively,
//  it can be called every time a data frame arrives, regardless of whether 
//  the queue was previously empty or not. To do this, set 
//  KSPIN_FLAG_INITIATE_PROCESSING_ON_EVERY_ARRIVAL. Or, to indicate that 
//  this routine should never be called except in the event of a minidriver 
//  call to KsPinAttemptProcessing, set KSPIN_FLAG_DO_NOT_INITIATE_PROCESSING.
//
NTSTATUS  HwcapPin::OnProcess()
{
	g_Trace << "HwcapPin::OnProcess()" << EOL;

	NTSTATUS Status=STATUS_SUCCESS;

	// What's going on over here:
	//
	// 1) Get the leading edge stream pointer. It's locked by default;
	// 2) Clone the leading edge pointer into the "current" stream pointer;
	// 3) Program the "DMA Hardware" with the current pointer mappings. In essense,
	//    this would queue on-the-fly some "dma buffers" to-be-filled onto the hardware;
	// 4) Advance the leading pointer by the number of mappings queued to the hardware.
	//    Note that the current frame is "locked" by the current stream pointer referencing it;
	// 5) Return. Note that no data transfer happens yet; the generated image data are moved
	//    into the queued "dma buffers" on the faked interrupt. At that time the current
	//    stream pointer gets unlocked, which in turn, frees the pointed frame and let it
	//    move by AVStream off the pin to the next node in the graph.

	KsStreamLeadingPointer	Leading(*this);
	KsStreamPointer			Clone;
	StreamPointerContext_t*	pContext;

	if (Leading.IsValid()) {
		
		if (m_Current.IsValid()) {
			
			// still processing previous frame
			
			Clone = m_Current;
			pContext = m_Current.Context(this);
			
			// g_Trace.Trace(TraceInfo, "Processing PREVIOUS clone %p\n", PKSSTREAM_POINTER (Clone));
		}
		
		else {
			
			// New frame: get new clone for the leading
			
			Clone = Leading.Clone(this);
			
			if (Clone.IsValid()) {
				
				// g_Trace.Trace(TraceInfo, "Processing NEW clone %p\n", PKSSTREAM_POINTER (Clone));

				// Store the context. 
				
				pContext = Clone.Context(this);
				pContext->VirtualBuffer = (PUCHAR) PKSSTREAM_HEADER(Clone)->Data;
				PKSSTREAM_HEADER(Clone)->DataUsed = 0;
			}
			else {
				g_Trace.Trace(TraceWarning, "HwcapPin::OnProcess - can't clone\n");
				Leading.Unlock();
				ReturnPending();
			}
		}

		// Program hardware. If we didn't use all the mappings, save the current
		// stream pointer for the next OnProcess():

		KSSTREAM_POINTER_OFFSET& Mapping = PKSSTREAM_POINTER(Leading)->OffsetOut;

		if (Mapping.Remaining) {

			ULONG MappingsUsed = m_pHardware->SetupDma(&pContext->VirtualBuffer, Mapping);

			m_Current = (MappingsUsed == Mapping.Remaining) ? (PKSSTREAM_POINTER) NULL : Clone;

			// If we added mappings, then the h/w still has resources => advance the leading edge. 
			// Otherwise pend until h/w release some resources on interrupt

			Status = (MappingsUsed) ? Leading.AdvanceOut(MappingsUsed) : STATUS_PENDING;
		}
		else { 
			g_Trace.Trace(TraceWarning, "HwcapPin::OnProcess - no mappings in the stream\n");
			Status = STATUS_PENDING;
		}

		// Unlock the leading so that more data can be added.
		// STATUS_DEVICE_NOT_READY indicates we ran off the end of the queue

		if (NT_SUCCESS (Status))
			Leading.Unlock();
		else if (Status == STATUS_DEVICE_NOT_READY)
			Status = STATUS_SUCCESS;
	}
	else {
		g_Trace.Trace(TraceWarning, "HwcapPin::OnProcess - leading edge not avail.\n");
		ReturnPending();
	}


	if (!NT_SUCCESS (Status) || Status == STATUS_PENDING)
        m_bPending = TRUE;

	return Status;
}

///////////////////////////////////////////////////////////////////////
// HwcapPin::OnSetDataFormat
//
// Parameters:
//  Pin				 -	   Pin to be created
// 	DataRange            - A range out of our list of data ranges which was 
//                         determined to be at least a partial match for Pin -> ConnectionFormat.
// 	AttributeRange       - The attribute range
// Returns:
// 	STATUS_SUCCESS if Pin's ConnectionFormat member matches the range 
//  that was passed to this routine.
//  STATUS_NO_MATCH if ConnectionFormat does not match the passed range. 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -