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

📄 basepin.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
字号:
/*+++ *******************************************************************\
*
*   Copyright and Disclaimer:
*
*       ---------------------------------------------------------------
*     This software is provided "AS IS" without warranty of any kind, 
*     either expressed or implied, including but not limited to the 
*     implied warranties of noninfringement, merchantability and/or 
*     fitness for a particular purpose.
*       ---------------------------------------------------------------
*
*     Copyright (c) 2008 Conexant Systems, Inc. 
*     All rights reserved. 
*
\******************************************************************* ---*/

#include "BasePin.h"
#include "Device.h"
#include "cpprt.h"
#include "debug.h"

BasePin::BasePin(PKSPIN  p_ks_pin):
    _picture_num(0),
    _dropped_cnt(0),
    _p_ks_pin(p_ks_pin),
    _p_device(NULL),
    _p_clock(NULL),
    _discontinuity(FALSE),
    _frame_size(0),
    _duration(0)
{
}


BasePin::~BasePin()
{
    if(_p_ks_pin->ClientState != KSSTATE_STOP)
	{
		DbgLogError(("BasePin: ~BasePin: client state is not set to STOP yet..\n"));
	}
    
    if(_p_clock)
    {
        _p_clock->Release();
        _p_clock = NULL;
    }

    //Make sure we aren't holding resources
    if(_p_device)
    {
        _p_device->releaseResources(this);
		_p_device = NULL;
    }
}


NTSTATUS BasePin::dispatchClose(PKSPIN p_ks_pin, PIRP  p_irp)
{
    delete reinterpret_cast<BasePin*>(p_ks_pin->Context);
    p_ks_pin->Context = NULL;
    return STATUS_SUCCESS;
}


NTSTATUS BasePin::dispatchProcess(PKSPIN p_ks_pin)
{
    return STATUS_PENDING;
}


NTSTATUS BasePin::dispatchSetState(
                                   PKSPIN   p_ks_pin, 
                                   KSSTATE  to_state,
                                   KSSTATE  from_state)
{
    return (reinterpret_cast<BasePin*>(p_ks_pin->Context))->
        setState(to_state, from_state);
}


NTSTATUS BasePin::getDroppedFrames(
                                   PIRP                                p_irp,
                                   PKSPROPERTY                         p_in,
                                   PKSPROPERTY_DROPPEDFRAMES_CURRENT_S p_out)
{
    PKSPIN p_ks_pin = KsGetPinFromIrp(p_irp);

    if(p_ks_pin)
	{
    
		BasePin* p_pin = (BasePin*)p_ks_pin->Context;

		p_out->PictureNumber    = p_pin->_picture_num;
		p_out->DropCount        = p_pin->_dropped_cnt;
		p_out->AverageFrameSize = p_pin->_frame_size;

		return STATUS_SUCCESS;
	}
	else
		return STATUS_UNSUCCESSFUL;
}


NTSTATUS BasePin::init(
                       ULONG             frames_to_cycle,
                       ULONG             frame_size,
                       LONGLONG          duration)
{            
    _frame_size = frame_size;
    _duration   = duration;

    PKSDEVICE p_ks_dev = KsPinGetDevice(_p_ks_pin);
    _p_device          = static_cast<Device*>(p_ks_dev->Context);

    // We need to KsEdit the descriptor to ensure we don't mess up 
    // any other pins using the descriptor or touch read-only memory.
    NTSTATUS status = KsEdit( _p_ks_pin, &_p_ks_pin->Descriptor, 'TXNC');

    if(NT_SUCCESS(status))
    {
        status = KsEdit( 
            _p_ks_pin, 
            &_p_ks_pin->Descriptor->AllocatorFraming,
            'TXNC');
    }

    // If the KsEdits proceeded without running out of memory, 
    // adjust the framing based on the video info header.
    if(NT_SUCCESS(status)) 
    {
        // It is safe to cast away constness as 
        // long as the KsEdit succeeded.
        KSALLOCATOR_FRAMING_EX *p_framing = 
            const_cast<KSALLOCATOR_FRAMING_EX*>
            ( _p_ks_pin->Descriptor->AllocatorFraming );

        // Indicate how many frames we what to cycle through.
        p_framing->FramingItem[0].Frames = frames_to_cycle;

        // We only support one frame size, the size of each capture image.
        p_framing->FramingItem[0].PhysicalRange.MinFrameSize          =
            p_framing->FramingItem[0].PhysicalRange.MaxFrameSize      =
            p_framing->FramingItem[0].FramingRange.Range.MinFrameSize =
            p_framing->FramingItem[0].FramingRange.Range.MaxFrameSize =
            _frame_size;

        p_framing->FramingItem[0].PhysicalRange.Stepping = 
            p_framing->FramingItem[0].FramingRange.Range.Stepping = 0;
        
        //make a different to video render, that will lead color convert insert auto
        p_framing->FramingItem[0].MemoryFlags = KSALLOCATOR_REQUIREMENTF_MUST_ALLOCATE;
    }
    
    return status;
}

VOID BasePin::timeStamp( 
                        PKSSTREAM_HEADER  p_strm_hdr, 
                        LONGLONG          time,
                        BOOLEAN           time_is_valid,
                        FIELD_TYPE        field_type)
{
    p_strm_hdr->Duration = _duration;

    p_strm_hdr->PresentationTime.Numerator   = 1;
    p_strm_hdr->PresentationTime.Denominator = 1;
    p_strm_hdr->PresentationTime.Time        = time_is_valid ? time : 0;

    p_strm_hdr->OptionsFlags  = 0;
    p_strm_hdr->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
    
    if( time_is_valid )
         p_strm_hdr->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_TIMEVALID;

    if( _discontinuity )
    {
        p_strm_hdr->OptionsFlags |= 
            KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
        _discontinuity = false;
    }

    // Call into derived calls to set the frame info members.
    fillFrameInfo(p_strm_hdr, field_type);
}


//////////////////////////////////////////////////////////////////////////////////
//AudioPin::getNextBuffer
//
// This function is called by the RiscEngine class when it is ready to add a 
// program for a buffer.  
//
// This function always returns a pointer to the next buffer in the queue.
//
// A note on AVStream buffering:
//   In order to DMA to a buffer, the buffer needs to have a least one locked 
// pointer pointing to it.  The leading edge pointer may be acquired in a locked
// state, but it will be unlocked as soon as the pointer is advanced. So, in
// order to maintain several buffers in a locked state for the RISC engine, we
// need to create clone pointers, and keep them locked until the RISC engine
// finishes processing the buffer.  AVStream pins already have a queue for clone 
// pointers that allows accessing the pointers in the same order in which they 
// were cloned.  When the RISC engine completes a buffer, it calls onBufferComplete.
// this will then timestamp the buffer, unlock it and delete the clone pointer.
// Buffers must be completed in the same order they were retreived by calling this
// function.
//

PKSSTREAM_POINTER BasePin::getNextBuffer()
{
    if (!_p_ks_pin||_p_ks_pin->ClientState != KSSTATE_RUN)
    {
        return NULL;            
    } 

    //Get the leading edge buffer pointer.
    PKSSTREAM_POINTER p_leading_edge = KsPinGetLeadingEdgeStreamPointer(
        _p_ks_pin,
        KSSTREAM_POINTER_STATE_LOCKED);

    if(!p_leading_edge)
    {
        return NULL;
    }

    //Create a clone of the leading edge pointer
    //We need to create a clone of every pointer we are using so that the 
    // pointer will remain locked after we advance the leading edge pointer.
    // We don't need to save the clone pointer.  AVStream does that for us.
    PKSSTREAM_POINTER p_clone = NULL;

    NTSTATUS status = KsStreamPointerClone(
        p_leading_edge,
        NULL,               //For now, clones aren't cancelable.
        0,                  //No context
        &p_clone);

    //Unlock the leading edge pointer.  The clone is still in locked status
    KsStreamPointerUnlock(p_leading_edge, FALSE);

    //If we failed to create the clone, return
    if(!NT_SUCCESS(status))
    {
        return NULL;
    }

    //Advance the leading edge pointer so it points to the next buffer for next time.
    //(Always succeeds when the pointer is not locked)
    KsStreamPointerAdvance(p_leading_edge);

    return p_clone;
}

VOID BasePin::onBufferComplete(FIELD_TYPE field_type)
{
    //Get the first clone pointer.
    PKSSTREAM_POINTER p_clone = KsPinGetFirstCloneStreamPointer(_p_ks_pin);
    if(!p_clone)
    {
        //No buffer was available to complete.
        return;
    }

    LONGLONG system_time;
    timeStamp( 
        p_clone->StreamHeader, 
        _p_clock ? _p_clock->GetCorrelatedTime(&system_time) : 0, 
        _p_clock ? true : false,
        field_type);

    processCompletedBuffer(p_clone);


    //Unlock the clone pointer
    KsStreamPointerUnlock(p_clone, FALSE);

    //Delete the clone pointer
    KsStreamPointerDelete(p_clone);
}


VOID BasePin::releaseClones()
{
    PKSSTREAM_POINTER p_next_clone = NULL;
    PKSSTREAM_POINTER p_clone = KsPinGetFirstCloneStreamPointer(_p_ks_pin);

    // Walk through the clones, deleting them, and setting 
    // DataUsed to zero since we didn't dma any data.
    while(p_clone) 
    { 
        // Free the memory allocated by createRiscProg()
        p_clone->Context = NULL;

        p_next_clone = KsStreamPointerGetNextClone( p_clone ); 

        p_clone->StreamHeader->DataUsed = 0;
        KsStreamPointerDelete( p_clone );

        p_clone = p_next_clone;
    }
}


NTSTATUS BasePin::setState(KSSTATE to_state, KSSTATE from_state)
{
    NTSTATUS status = STATUS_SUCCESS;    

    switch(to_state) 
    {
    case KSSTATE_STOP:
        status = _p_device->stop(this);
        _p_device->releaseResources(this);

        releaseClones();
        
        if( _p_clock )
        {
            _p_clock->Release();
            _p_clock = NULL;
        }
        
       
        break;
        
    case KSSTATE_ACQUIRE:
        
        // We should only acquire hardware resources here, not at 
        // pin create time.  This means we do not fail creation 
        // of a pin because of limited hardware resources.
        
        if(!_p_device->acquireResources(this))
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
        
        if( from_state == KSSTATE_STOP ) 
        {
            if( NT_SUCCESS( status ) )
            {
                KsPinGetReferenceClockInterface(_p_ks_pin, &_p_clock);
            }

            //We are supposed to reset the picture count when transitioning from stop to run
            // (If we do it when transitioning between pause and run, 
            //   we get a direct x assertion failure)
            resetCounters();

        }
        
        break;
        
    case KSSTATE_PAUSE:
        
        if( from_state == KSSTATE_RUN )
        {
            status = _p_device->stop(this);
            
            releaseClones();
        }
        
        break;
        
    case KSSTATE_RUN:
        
        _discontinuity = TRUE;
        start();
        
        //We'll fail to start only if we did not acquire the resources
		status = _p_device->start(this);
        
        break;
    }
    
    return status;
}

VOID BasePin::resetCounters()
{
    _picture_num   = 0;
    _dropped_cnt   = 0;
    _discontinuity = FALSE;
}


VOID BasePin::droppedFrame()
{
    _picture_num++;
    _dropped_cnt++;
    _discontinuity = TRUE;
}

DECLARE_SIMPLE_FRAMING_EX 
(
    PIN_ALLOCATOR_FRAMING,
    STATICGUIDOF( KSMEMORY_TYPE_KERNEL_NONPAGED ),
    KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
        KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY,
    2,
    0,
    2 * PAGE_SIZE,
    2 * PAGE_SIZE
);


const 
KSPROPERTY_ITEM 
PIN_DROPPED_FRAMES_PROPERTIES[] =
{
   DEFINE_KSPROPERTY_ITEM
   (
      KSPROPERTY_DROPPEDFRAMES_CURRENT,
      BasePin::getDroppedFrames,                 // GetSupported or Handler
      sizeof(KSPROPERTY_DROPPEDFRAMES_CURRENT_S),// MinProperty
      sizeof(KSPROPERTY_DROPPEDFRAMES_CURRENT_S),// MinData
      NULL,                                      // SetSupported or Handler
      NULL,                                      // Values
      0,                                         // RelationsCount
      NULL,                                      // Relations
      NULL,                                      // SupportHandler
      0                                          // SerializedSize
   )
};


const 
KSPROPERTY_SET 
PIN_PROPERTIES[] =
{
    DEFINE_KSPROPERTY_SET
    (
        &PROPSETID_VIDCAP_DROPPEDFRAMES,            // Set
        SIZEOF_ARRAY( PIN_DROPPED_FRAMES_PROPERTIES ),// PropertiesCount
        PIN_DROPPED_FRAMES_PROPERTIES,              // PropertyItem
        0,                                          // FastIoCount
        NULL                                        // FastIoTable
    )
};


const 
KSAUTOMATION_TABLE
PIN_AUTOMATION_TABLE = 
{
    DEFINE_KSAUTOMATION_PROPERTIES( PIN_PROPERTIES ),
    DEFINE_KSAUTOMATION_METHODS_NULL,
    DEFINE_KSAUTOMATION_EVENTS_NULL
};

⌨️ 快捷键说明

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