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

📄 vbipin.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 "VbiPin.h"
#include "debug.h"
#include "pindataranges.h"
#include "ivideoDecoder.h"
#include "device.h"

const ULONG VBI_FRAMES_TO_CYCLE = 8;

const DWORD SIXTY_HZ_MASK = 
    KS_AnalogVideo_NTSC_Mask | 
    KS_AnalogVideo_PAL_M     |
    KS_AnalogVideo_PAL_60;


DWORD VbiPin::getLineSize()
{
    return 1440;
}

DWORD VbiPin::getLinesPerFrame()
{
    return _lines_per_frame;
}



VbiPin::VbiPin( 
               PKSPIN     p_ks_pin,
               NTSTATUS  &status):
BasePin(p_ks_pin),
_tv_info_changed(TRUE)
{
    _info_hdr = ((reinterpret_cast<KS_DATAFORMAT_VBIINFOHEADER*> 
                    (p_ks_pin->ConnectionFormat))->VBIInfoHeader);    

    LONG duration = _info_hdr.VideoStandard & SIXTY_HZ_MASK ? 
                    FIELD_DURATION_60HZ : FIELD_DURATION_50HZ; 

    // Init the base class    
    status = init(
        VBI_FRAMES_TO_CYCLE,
        _info_hdr.BufferSize,
        duration);

    // This needs to be done so that the KSSTREAM_HEADER in the 
    // KSSTEAM_POINTER has the correct size for fillFrameInfo()    
    if(NT_SUCCESS(status))
    {
        p_ks_pin->StreamHeaderSize = 
            sizeof(KSSTREAM_HEADER) + sizeof(KS_VBI_FRAME_INFO);
    }

    //Initialize the TV info structure.  This will get sent the 
    // first time the VBI pin starts if no channel change actually occured.  
    // The CC decoder doesn't start decoding until it has seen the flag at least once.
    _tv_info.dwFlags = KS_TVTUNER_CHANGE_END_TUNE;
    _tv_info.dwCountryCode = 1;
    _tv_info.dwAnalogVideoStandard = KS_AnalogVideo_NTSC_M;
    _tv_info.dwChannel = 4;

    _lines_per_frame = 
        (_info_hdr.VideoStandard & NTSC_ASPECT_VIDEO_STANDARDS) ? 
            NTSC_VBI_LINES : PAL_VBI_LINES; 

    _lines_per_frame *= 2;

}


NTSTATUS VbiPin::dispatchCreate(PKSPIN  p_ks_pin,
                                PIRP p_irp)
{
    NTSTATUS status = STATUS_SUCCESS;

    p_ks_pin->Context = new VbiPin(p_ks_pin, status);

    if(!p_ks_pin->Context)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    if(!NT_SUCCESS(status))
    {
        delete (VbiPin*)p_ks_pin->Context;
    }

    return status;
}


VOID VbiPin::fillFrameInfo(PKSSTREAM_HEADER p_strm_hdr, FIELD_TYPE field_type)
{
    // This size is obtained from KSPIN->StreamHeaderSize 
    // which we initialize in the ctor
    if(p_strm_hdr->Size < (sizeof(KSSTREAM_HEADER) + sizeof(KS_VBI_FRAME_INFO)))
    {
        DbgLogError(( 
            "VbiPin::fillFrameInfo Size = %d\n", 
            p_strm_hdr->Size));
        return;
    }

    KS_VBI_FRAME_INFO *p_frame_info = 
        reinterpret_cast<KS_VBI_FRAME_INFO*>(p_strm_hdr + 1);

    p_frame_info->ExtendedHeaderSize = sizeof KS_VBI_FRAME_INFO;

    p_frame_info->PictureNumber       = ++_picture_num;
    p_frame_info->DropCount           = _dropped_cnt;
    p_frame_info->dwSamplingFrequency = _info_hdr.SamplingFrequency;

    p_frame_info->dwFrameFlags = 
        (field_type == FIELD_1) ? KS_VBI_FLAG_FIELD1 : KS_VBI_FLAG_FIELD2;

    if(_tv_info_changed)
    {
        p_frame_info->TvTunerChangeInfo  = _tv_info;
        p_frame_info->dwFrameFlags      |= KS_VBI_FLAG_TVTUNER_CHANGE;


        //We need to set the VBI Info Header here for the CC decoder to get the
        // correct format. This needs to be done once after we start
        p_frame_info->dwFrameFlags |= KS_VBI_FLAG_VBIINFOHEADER_CHANGE;


        IVideoDecoder* p_decoder = _p_device->getVidDec();
        KS_VBIINFOHEADER* p_header = &g_stream_format_VBI.VBIInfoHeader;
        DWORD  VideoMode = p_decoder->getVideoMode();
        if(( VideoMode == VIDEO_MODE_PAL)||
            (VideoMode == VIDEO_MODE_SECAM)||
            (VideoMode == VIDEO_MODE_PAL_N)||
            (VideoMode == VIDEO_MODE_PAL_NC))
        {
            p_header = &g_stream_format_VBI_PAL.VBIInfoHeader;
        }
        
        RtlCopyMemory(
            &p_frame_info->VBIInfoHeader,
            p_header,
            sizeof(KS_VBIINFOHEADER));


        _tv_info_changed = false;
    }


}

VOID VbiPin::start()
{
    _tv_info_changed = TRUE;
}



NTSTATUS VbiPin::intersectRange(PKSFILTER                p_filter,
                                PIRP                     p_irp,
                                PKSP_PIN                 p_pin_instance,
                                PKS_DATARANGE_VIDEO_VBI  p_caller_range,
                                PKS_DATARANGE_VIDEO_VBI  p_our_range,
                                ULONG                    buffer_size,
                                PVOID                    p_data,
                                PULONG                   p_data_size)
{
    if(!IsEqualGUID(
            p_caller_range->DataRange.Specifier, 
            KSDATAFORMAT_SPECIFIER_VBI))
    {
        return STATUS_NO_MATCH;
    }

    // Check that all the members of the two DATARANGES are the same
    if((p_caller_range->bFixedSizeSamples != p_our_range->bFixedSizeSamples) ||
       (p_caller_range->bTemporalCompression != p_our_range->bTemporalCompression) ||
       (p_caller_range->StreamDescriptionFlags != p_our_range->StreamDescriptionFlags) ||
       (p_caller_range->MemoryAllocationFlags != p_our_range->MemoryAllocationFlags) ||
       (RtlCompareMemory( 
            &p_caller_range->ConfigCaps, 
            &p_our_range->ConfigCaps, 
            sizeof(KS_VIDEO_STREAM_CONFIG_CAPS)) != sizeof(KS_VIDEO_STREAM_CONFIG_CAPS)) ||
       (RtlCompareMemory( 
            &p_caller_range->VBIInfoHeader, 
            &p_our_range->VBIInfoHeader, 
            sizeof(KS_VBIINFOHEADER)) != sizeof(KS_VBIINFOHEADER)))
    {
        DbgLogError(("Vbi intersect NO MATCH\n"));
        return STATUS_NO_MATCH;
    }

    // Set the required output buffer size
    *p_data_size = sizeof KS_DATAFORMAT_VBIINFOHEADER;

    // If buffer_size is 0 this is a size query
    if(buffer_size == 0)
    {
        return STATUS_BUFFER_OVERFLOW;
    }

    // Check that the output data buffer is large enough
    if(buffer_size < *p_data_size)
    {
        return STATUS_BUFFER_TOO_SMALL;
    }

    // Copy the data range structure from our 
    // decriptor into the target format buffer
    KS_DATAFORMAT_VBIINFOHEADER *p_out_format =
        reinterpret_cast<KS_DATAFORMAT_VBIINFOHEADER*>(p_data);

    p_out_format->DataFormat =
        static_cast<KSDATAFORMAT>(p_our_range->DataRange);

    // Since the input structs are KS_DATARANGE_VIDEO_VBI and the
    // output struct is a KS_DATAFORMAT_VBIINFOHEADER we need
    // to set the FormatSize according to the output struct.
    p_out_format->DataFormat.FormatSize = *p_data_size;

    // Copy the KS_VBIINFOHEADER to the output struct
    p_out_format->VBIInfoHeader = p_our_range->VBIInfoHeader;

    return STATUS_SUCCESS;
}

PIN_TYPES VbiPin::getPinType()
{
    return PIN_TYPE_VBI; 
}



VOID VbiPin::setTVInfo(PKS_TVTUNER_CHANGE_INFO p_tv_info)
{
    _tv_info         = *p_tv_info;
    _tv_info_changed = TRUE;
}


NTSTATUS VbiPin::dispatchSetFormat(PKSPIN            p_ks_pin, 
                                   PKSDATAFORMAT     p_old_data_format,
                                   PKSMULTIPLE_ITEM  p_attr_list,
                                   PKSDATARANGE      p_range,
                                   PKSATTRIBUTE_LIST p_attr_range)
{ 
    if( IsEqualGUID( p_ks_pin->ConnectionFormat->Specifier,
                     KSDATAFORMAT_SPECIFIER_VBI ) )
    {
        if( p_ks_pin->ConnectionFormat->FormatSize < 
            sizeof(KS_DATAFORMAT_VBIINFOHEADER))
                return STATUS_INVALID_PARAMETER;

        KS_DATAFORMAT_VBIINFOHEADER *p_new_format = 
            (KS_DATAFORMAT_VBIINFOHEADER*)
            p_ks_pin->ConnectionFormat;


        KS_DATARANGE_VIDEO_VBI* p_our_range = 
            (KS_DATARANGE_VIDEO_VBI*) p_range;

        //Make sure the format is correct
        if((p_new_format->VBIInfoHeader.StartLine != p_our_range->VBIInfoHeader.StartLine) ||
            (p_new_format->VBIInfoHeader.EndLine != p_our_range->VBIInfoHeader.EndLine)    ||
            (p_new_format->VBIInfoHeader.SamplesPerLine != p_our_range->VBIInfoHeader.SamplesPerLine)    ||
            (p_new_format->VBIInfoHeader.BufferSize != p_our_range->VBIInfoHeader.BufferSize) ||
            (p_new_format->DataFormat.SampleSize != p_our_range->VBIInfoHeader.BufferSize))
        {
            return STATUS_NO_MATCH;
        }

        return STATUS_SUCCESS;
    }

    return STATUS_NO_MATCH;
}



const KSPIN_DISPATCH VbiPinDispatch = 
{
    VbiPin::dispatchCreate,       // Pin Create
    BasePin::dispatchClose,       // Pin Close
    BasePin::dispatchProcess,     // Pin Process
    NULL,                         // Pin Reset
    (PFNKSPINSETDATAFORMAT)VbiPin::dispatchSetFormat,    // Pin Set Data Format
    BasePin::dispatchSetState,    // Pin Set Device State
    NULL,                         // Pin Connect
    NULL,                         // Pin Disconnect
    NULL,                         // Clock Dispatch
    NULL                          // Allocator Dispatch
};

⌨️ 快捷键说明

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