**************************************************************************/

GUID g_PINNAME_VIDEO_CAPTURE = {STATIC_PINNAME_VIDEO_CAPTURE};
GUID g_PINNAME_VIDEO_PREVIEW = {STATIC_PINNAME_VIDEO_PREVIEW};
GUID g_PINNAME_IMAGE_CAPTURE = {STATIC_PINNAME_IMAGE};

//
// CaptureFilterCategories:
//
// The list of category GUIDs for the capture filter.
//
const
GUID
FilterCategories [CAPTURE_FILTER_CATEGORIES_COUNT] =
{
    STATICGUIDOF (KSCATEGORY_VIDEO_CAMERA),
    STATICGUIDOF (KSCATEGORY_VIDEO),
    STATICGUIDOF (KSCATEGORY_CAPTURE)
};

DEFINE_KSPROPERTY_TABLE(FocusPropertyItems)
{
    DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID, KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_S, FocusRect )
};

DEFINE_KSPROPERTY_TABLE(VideoStabPropertyItems)
{
    DEFINE_PROP_ITEM( CCaptureFilter, 0, KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode )
};

DEFINE_KSPROPERTY_TABLE(FlashPropertyItems)
Example #2
0
        STATUS_SUCCESS -
            The format is acceptable / the format has been changed

        STATUS_NO_MATCH -
            The format is not-acceptable / the format has not been changed

--*/

{
    PAGED_CODE();
    DBGU_TRACE("Enter CStillPin::DispatchSetFormat\n");

    NTSTATUS Status = STATUS_NO_MATCH;

    const GUID VideoInfoSpecifier =
    {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};

    CStillPin *StiPin = NULL;

    //
    // Find the pin, if it exists yet.  OldFormat will be an indication of
    // this.  If we're changing formats, OldFormat will be non-NULL.
    //
    // You cannot use Pin -> Context to make the determination.  AVStream
    // preinitializes this to the filter's context.
    //
    if (OldFormat) {
        StiPin = reinterpret_cast <CStillPin *> (Pin -> Context);
    }

    if (IsEqualGUID (Pin -> ConnectionFormat -> Specifier, VideoInfoSpecifier) &&
Example #3
0
NTSTATUS
CStillPin::
IntersectHandler (
    IN PKSFILTER Filter,
    IN PIRP Irp,
    IN PKSP_PIN PinInstance,
    IN PKSDATARANGE CallerDataRange,
    IN PKSDATARANGE DescriptorDataRange,
    IN ULONG BufferSize,
    OUT PVOID Data OPTIONAL,
    OUT PULONG DataSize
)

/*++

Routine Description:

    This routine handles video pin intersection queries by determining the
    intersection between two data ranges.

Arguments:

    Filter -
        Contains a void pointer to the  filter structure.

    Irp -
        Contains a pointer to the data intersection property request.

    PinInstance -
        Contains a pointer to a structure indicating the pin in question.

    CallerDataRange -
        Contains a pointer to one of the data ranges supplied by the client
        in the data intersection request.  The format type, subtype and
        specifier are compatible with the DescriptorDataRange.

    DescriptorDataRange -
        Contains a pointer to one of the data ranges from the pin descriptor
        for the pin in question.  The format type, subtype and specifier are
        compatible with the CallerDataRange.

    BufferSize -
        Contains the size in bytes of the buffer pointed to by the Data
        argument.  For size queries, this value will be zero.

    Data -
        Optionally contains a pointer to the buffer to contain the data
        format structure representing the best format in the intersection
        of the two data ranges.  For size queries, this pointer will be
        NULL.

    DataSize -
        Contains a pointer to the location at which to deposit the size
        of the data format.  This information is supplied by the function
        when the format is actually delivered and in response to size
        queries.

Return Value:

    STATUS_SUCCESS if there is an intersection and it fits in the supplied
    buffer, STATUS_BUFFER_OVERFLOW for successful size queries,
    STATUS_NO_MATCH if the intersection is empty, or
    STATUS_BUFFER_TOO_SMALL if the supplied buffer is too small.

--*/

{
    PAGED_CODE();
    DBGU_TRACE("Enter CStillPin::IntersectHandler\n");

    const GUID VideoInfoSpecifier =
    {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};

    ASSERT(Filter);
    ASSERT(Irp);
    ASSERT(PinInstance);
    ASSERT(CallerDataRange);
    ASSERT(DescriptorDataRange);
    ASSERT(DataSize);

    ULONG DataFormatSize;

    //
    // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER2
    //
    if (IsEqualGUID(CallerDataRange->Specifier, VideoInfoSpecifier) &&
            CallerDataRange -> FormatSize >= sizeof (KS_DATARANGE_VIDEO)) {

        PKS_DATARANGE_VIDEO callerDataRange =
            reinterpret_cast <PKS_DATARANGE_VIDEO> (CallerDataRange);

        PKS_DATARANGE_VIDEO descriptorDataRange =
            reinterpret_cast <PKS_DATARANGE_VIDEO> (DescriptorDataRange);

        PKS_DATAFORMAT_VIDEOINFOHEADER FormatVideoInfoHeader;

        //
        // Check that the other fields match
        //
        if ((callerDataRange->bFixedSizeSamples !=
                descriptorDataRange->bFixedSizeSamples) ||
                (callerDataRange->bTemporalCompression !=
                 descriptorDataRange->bTemporalCompression) ||
                (callerDataRange->StreamDescriptionFlags !=
                 descriptorDataRange->StreamDescriptionFlags) ||
                (callerDataRange->MemoryAllocationFlags !=
                 descriptorDataRange->MemoryAllocationFlags) ||
                (RtlCompareMemory (&callerDataRange->ConfigCaps,
                                   &descriptorDataRange->ConfigCaps,
                                   sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
                 sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
        {
            DBGU_TRACE("Check that the other fields match, return STATUS_NO_MATCH\n");
            return STATUS_NO_MATCH;
        }

        //
        // KS_SIZE_VIDEOHEADER() below is relying on bmiHeader.biSize from
        // the caller's data range.  This **MUST** be validated; the
        // extended bmiHeader size (biSize) must not extend past the end
        // of the range buffer.  Possible arithmetic overflow is also
        // checked for.
        //
        {
            ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
                                        &callerDataRange->VideoInfoHeader
                                    );

            ULONG DataRangeSize =
                FIELD_OFFSET (KS_DATARANGE_VIDEO, VideoInfoHeader) +
                VideoHeaderSize;

            DBGU_TRACE("X=%d, Y=%d, BI=%d\n",callerDataRange->VideoInfoHeader.bmiHeader.biWidth,
                       callerDataRange->VideoInfoHeader.bmiHeader.biHeight,
                       callerDataRange->VideoInfoHeader.bmiHeader.biBitCount);
            //
            // Check that biSize does not extend past the buffer.  The
            // first two checks are for arithmetic overflow on the
            // operations to compute the alleged size.  (On unsigned
            // math, a+b < a iff an arithmetic overflow occurred).
            //
            if (VideoHeaderSize < callerDataRange->VideoInfoHeader.bmiHeader.biSize ||
                    DataRangeSize < VideoHeaderSize ||
                    DataRangeSize > callerDataRange -> DataRange.FormatSize
               ) {
                DBGU_TRACE("Check that biSize, return STATUS_INVALID_PARAMETER\n");
                return STATUS_INVALID_PARAMETER;
            }
        }

        DataFormatSize =
            sizeof (KSDATAFORMAT) +
            KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader);

        //
        // If the passed buffer size is 0, it indicates that this is a size
        // only query.  Return the size of the intersecting data format and
        // pass back STATUS_BUFFER_OVERFLOW.
        //
        if (BufferSize == 0) {
            *DataSize = DataFormatSize;
            DBGU_TRACE("the passed buffer size is 0, return STATUS_BUFFER_OVERFLOW\n");
            return STATUS_BUFFER_OVERFLOW;
        }

        //
        // Verify that the provided structure is large enough to
        // accept the result.
        //
        if (BufferSize < DataFormatSize)
        {
            DBGU_TRACE("Verify buffer large enough, return STATUS_BUFFER_TOO_SMALL\n");
            return STATUS_BUFFER_TOO_SMALL;
        }

        //
        // Copy over the KSDATAFORMAT, followed by the actual VideoInfoHeader
        //
        *DataSize = DataFormatSize;

        FormatVideoInfoHeader = PKS_DATAFORMAT_VIDEOINFOHEADER( Data );

        //
        // Copy over the KSDATAFORMAT.  This is precisely the same as the
        // KSDATARANGE (it's just the GUIDs, etc...  not the format information
        // following any data format.
        //
        RtlCopyMemory (
            &FormatVideoInfoHeader->DataFormat,
            DescriptorDataRange,
            sizeof (KSDATAFORMAT));

        FormatVideoInfoHeader->DataFormat.FormatSize = DataFormatSize;

        //
        // Copy over the callers requested VIDEOINFOHEADER
        //

        RtlCopyMemory (
            &FormatVideoInfoHeader->VideoInfoHeader,
            &callerDataRange->VideoInfoHeader,
            KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader)
        );

        //
        // Calculate biSizeImage for this request, and put the result in both
        // the biSizeImage field of the bmiHeader AND in the SampleSize field
        // of the DataFormat.
        //
        // Note that for compressed sizes, this calculation will probably not
        // be just width * height * bitdepth
        //
        FormatVideoInfoHeader->VideoInfoHeader.bmiHeader.biSizeImage =
            FormatVideoInfoHeader->DataFormat.SampleSize =
                KS_DIBSIZE (FormatVideoInfoHeader->VideoInfoHeader.bmiHeader);

        //
        // REVIEW - Perform other validation such as cropping and scaling checks
        //
        DBGU_TRACE("REVIEW - Perform other validation such as cropping and scaling checks\n");
        return STATUS_SUCCESS;

    } // End of VIDEOINFOHEADER specifier

    DBGU_TRACE("End of VIDEOINFOHEADER specifier, return STATUS_NO_MATCH\n");
    return STATUS_NO_MATCH;
}
Example #4
0
#define WAVE_FORMAT_WMA_SPDIF 0x164
#define STATIC_KSDATAFORMAT_SUBTYPE_WMA_SPDIF DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_WMA_SPDIF)
DEFINE_GUIDSTRUCT("00000164-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_WMA_SPDIF);
#define KSDATAFORMAT_SUBTYPE_WMA_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_WMA_SPDIF)

static KSDATARANGE_AUDIO WavePinDataRangesPCMStream[] =
{
    {
        {
            {
                sizeof(KSDATARANGE_AUDIO),
                0,
                0,
                0,
                {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)},
                {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)},
                {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)}
            }
        },
        MAX_CHANNELS_PCM,
        MIN_BITS_PER_SAMPLE_PCM,
        MAX_BITS_PER_SAMPLE_PCM,
        MIN_SAMPLE_RATE,
        MAX_SAMPLE_RATE
    }
};

static KSDATARANGE_AUDIO WavePinDataRangesAC3Stream[] =
{
    {
Example #5
0
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
};
Example #6
0
#define STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF\
    DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF)
DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF);
#define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF)
#endif


static KSDATARANGE PinDataRangesBridge[] =
{
    {
        {
            sizeof(KSDATARANGE),
            0,
            0,
            0,
            {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)},
            {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG)},
            {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)}
        }
    }
};

static PKSDATARANGE PinDataRangePointersBridge[] =
{
    &PinDataRangesBridge[0]
};

static KSDATARANGE WavePinDataRangesAC3Bridge[] =
{
	{
        {
    DBG_LEAVE("(Pin=%d)=0x%08X", Pin->Id, Status);
    return Status;
}

//
// CapturePinDispatch:
//
// This is the dispatch table for the capture pin.  It provides notifications
// about creation, closure, processing, data formats, etc...
//
DEFINE_CAMERA_KSPIN_DISPATCH( VideoCapturePinDispatch, CVideoCapturePin );

//
// CapturePinAllocatorFraming:
//
// 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.
//
DECLARE_SIMPLE_FRAMING_EX(
    VideoCapturePinAllocatorFraming,
    STATICGUIDOF( KSMEMORY_TYPE_KERNEL_NONPAGED ),
    KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
    KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY,
    2,
    0,
    2 * PAGE_SIZE,
    2 * PAGE_SIZE
);


**************************************************************************/

//=====================首先是Pin相关的描述符

// 输入/输出Pin所支持的数据格式,这其实是一个格式范围(Range)
// 在这个范围里面,可以设置最大、最小采用,最大最小采样深度
//
// 下面的结构体所表示的格式范围是:
// 双声道、24位采样、44.1或者48K采样率
KSDATARANGE_AUDIO gPinDataFormatRange =
{
    {
        sizeof(KSDATARANGE_AUDIO),
        0, 6, 0,
        STATIC_KSDATAFORMAT_TYPE_AUDIO,
        STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
        STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) 
    },
    2,          // channels
    16,         // min. bits per sample
    24,         // max. bits per sample
    44100,      // min. sample rate
    48000       // max. sample rate
};

const PKSDATARANGE gPinDataFormatRanges[] =
{
    PKSDATARANGE(&gPinDataFormatRange)
};

const KSPIN_DISPATCH gPinDispatch = 
Example #9
0
//////////////////////////////////////////////////////////////////////////////
//
// Description:
//  This is the intersect handler for comparison of a data range.
//  of the analog VBI out pin.(Needs no class environment to intersect
//  the format, because the format that is supported is already
//  given in the filter descriptor).
//
// Settings:
//  A match occurs under three conditions:
//  (1) if the major format of the range passed matches a pin factory range,
//  (2) if the sub-format matches,
//  (3) if the specifier is KSDATAFORMAT_SPECIFIER_VBI.
//  Since the data range size may be variable, it is not validated beyond
//  checking that it is at least the size of a data range structure.
//  (KSDATAFORMAT_SPECIFIER_VBI)
//
// Remarks:
//  There is a bug so we always get all formats from the descriptor 
//  even if they do not match with the current video standard detected
//  in the decoder property (see correct handling in the video classes).
//  To set up the right format, we ask the decoder for the current format 
//  and if it does not match to the pCallerDataRange, we return 
//  STATUS_NO_MATCH to get called again with the next format from the 
//  descriptor.
//  If it matches our decoder setting, we write it to the target format
//  pData.
//
// Return Value:
//  STATUS_SUCCESS           If a matching range is found and it fits
//                           in the supplied buffer.
//  STATUS_UNSUCCESSFUL      Operation failed,
//                           the function parameters are zero.
//  STATUS_BUFFER_OVERFLOW   For successful size queries. (in that case
//                           the buffer size is zero and has to be set
//                           to the right value before return)
//  STATUS_BUFFER_TOO_SMALL  If the supplied buffer is too small.
//  STATUS_NO_MATCH             (a) if the intersection is empty, or
//                              (b) if no matching range was found
//
//////////////////////////////////////////////////////////////////////////////
static
NTSTATUS AnlgVBIOutIntersectDataFormat
(
    IN PVOID pvKSFilter,                 //Pointer to KS filter structure.
    IN PIRP      pIrp,                      //Pointer to data intersection
                                            //property request.
    IN PKSP_PIN  pPinInstance,              //Pointer to structure indicating
                                            //pin in question.
    IN PKSDATARANGE pCallerDataRange,       //Pointer to the caller data
                                            //structure that should be
                                            //intersected.
    IN PKSDATARANGE pDescriptorDataRange,   //Pointer to the descriptor data
                                            //structure, see AnlgVbiFormats.h.
    IN ULONG     dwBufferSize,              //Size in bytes of the target
                                            //buffer structure. For size
                                            //queries, this value is zero.
    OUT OPTIONAL PVOID pData,               //Pointer to the target data
                                            //structure representing the best
                                            //format in the intersection.
    OUT PULONG   pdwDataSize                //Pointer to size of target data
                                            //format structure.
)
{

    PKSFILTER pKSFilter;
    pKSFilter = (PKSFILTER) pvKSFilter;
    DbgPrint("AnlgVBIOutIntersectDataFormat");
	
    //invalid parameters?
    if( !pKSFilter || !pIrp || !pPinInstance ||
        !pCallerDataRange || !pDescriptorDataRange || !pdwDataSize )
    {
		DbgPrint("SWTANALOG-Capture VBIOut UNSUCCESSFUL");
        return STATUS_UNSUCCESSFUL;
    }
    //set output data size
    *pdwDataSize = sizeof(KS_DATAFORMAT_VBIINFOHEADER);
    //check for size only query
    if( dwBufferSize == 0 )
    {
        //BUGBUG: we have to return "buffer overflow",
        //because this is what is expected on the other side,
        //any other return value will cause a wrong handling of
        //the size parameter
		DbgPrint("SWTANALOG-Capture VBIOut BUFFER_OVERFLOW");
        return STATUS_BUFFER_OVERFLOW;
    }
    //check if output buffer size is sufficient
    if( dwBufferSize < *pdwDataSize )
    {
		DbgPrint("SWTANALOG-Capture VBIOut TOO_SMALL");
        return STATUS_BUFFER_TOO_SMALL;
    }

    //*** start intersection ***//

    //check if given datarange GUID matches to VBI
    const GUID VBIInfoSpecifier =
        {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VBI)};
    if( !IsEqualGUID(pCallerDataRange->Specifier, VBIInfoSpecifier) ||
        pCallerDataRange->FormatSize != sizeof(KS_DATARANGE_VIDEO_VBI) )
    {
		DbgPrint("SWTANALOG-Capture VBIOut NO_MATCH 1");
        return STATUS_NO_MATCH;
    }

    PKS_DATARANGE_VIDEO_VBI pCallerVbiDataRange =
        reinterpret_cast <PKS_DATARANGE_VIDEO_VBI> (pCallerDataRange);
    PKS_DATARANGE_VIDEO_VBI pDescriptorVbiDataRange =
        reinterpret_cast <PKS_DATARANGE_VIDEO_VBI> (pDescriptorDataRange);
    PKS_DATAFORMAT_VBIINFOHEADER pTargetVbiDataRange =
        reinterpret_cast <PKS_DATAFORMAT_VBIINFOHEADER> (pData);

    //check if all other important fields match
    if(
        (pCallerVbiDataRange->bFixedSizeSamples !=
            pDescriptorVbiDataRange->bFixedSizeSamples) ||
        (pCallerVbiDataRange->bTemporalCompression !=
            pDescriptorVbiDataRange->bTemporalCompression) ||
        (pCallerVbiDataRange->StreamDescriptionFlags !=
            pDescriptorVbiDataRange->StreamDescriptionFlags) ||
        (pCallerVbiDataRange->MemoryAllocationFlags !=
            pDescriptorVbiDataRange->MemoryAllocationFlags)
       )
    {
		DbgPrint("SWTANALOG-Capture VBIOut NO_MATCH 2");
        return STATUS_NO_MATCH;
    }

    pTargetVbiDataRange->DataFormat =
        static_cast <KSDATAFORMAT> (pDescriptorVbiDataRange->DataRange);

    pTargetVbiDataRange->DataFormat.FormatSize = *pdwDataSize;

    pTargetVbiDataRange->VBIInfoHeader =
            pDescriptorVbiDataRange->VBIInfoHeader;

	DbgPrint("SWTANALOG-Capture VBIOut DataSize %d",*pdwDataSize);
	DbgPrint("SWTANALOG-Capture VBIOut success");
    return STATUS_SUCCESS;
}
Example #10
0
#include "ntintsafe.h"

#ifdef ALLOC_PRAGMA
#pragma code_seg("PAGE")
#endif // ALLOC_PRAGMA


/**************************************************************************

    DISPATCH AND DESCRIPTOR LAYOUT

**************************************************************************/

DEFINE_DATARANGE_VIDEO(
    FormatNV12_CaptureVGA,
    STATICGUIDOF(KSDATAFORMAT_SUBTYPE_NV12),
    DMAX_X, DMAX_Y,
    30,
    1,
    12,
    FOURCC_NV12)

DEFINE_DATARANGE_VIDEO(
    FormatYUY2_CaptureQVGA,
    STATICGUIDOF(KSDATAFORMAT_SUBTYPE_YUY2),
    D_X, D_Y,
    30,
    1,
    16,
    FOURCC_YUY2)