Ejemplo n.º 1
0
NTSTATUS CaptureFilterVideoInPinProcess ( IN PKSPIN pKSPin )
{
    PKSSTREAM_POINTER pStreamPointer = NULL;
    NTSTATUS          ntStatus       = STATUS_UNSUCCESSFUL;
    DbgPrint("CaptureFilterVideoInPinProcess");

    //parameters valid?
    if( !pKSPin )
    {
        DbgPrint("Error: CaptureFilterVideoInPinProcess: Invalid argument");
        return STATUS_UNSUCCESSFUL;
    }

    //get next available system buffer
    pStreamPointer = KsPinGetLeadingEdgeStreamPointer(
                                           pKSPin,
                                           KSSTREAM_POINTER_STATE_LOCKED);
    if( !pStreamPointer )
    {
        DbgPrint("Error: CaptureFilterVideoInPinProcess: Streampointer invalid");
        return STATUS_UNSUCCESSFUL;
    }

     if( !(pStreamPointer->StreamHeader) )
    {
        DbgPrint(
            "Error: AnlgVideoInPinProcess: Streampointer header invalid");
        if(KsStreamPointerAdvance(pStreamPointer) != STATUS_SUCCESS)
        {
            DbgPrint(
                "Warning: AnlgVideoInPinProcess:\
				Streampointer advacement failed");
        }
Ejemplo n.º 2
0
NTSTATUS CStillPin::Process ()

/*++

Routine Description:

    The process dispatch for the pin bridges to this location.
    We handle setting up scatter gather mappings, etc...

Arguments:

    None

Return Value:

    Success / Failure

--*/

{
    PAGED_CODE();

    NTSTATUS Status = STATUS_SUCCESS;
    PKSSTREAM_POINTER Leading=NULL;

    SnPrint(DEBUGLVL_VERBOSE, ("Enter CStillPin::Process\n"));
    ASSERT(m_Pin);

    if (!m_Device)
    {
        DBGU_ERROR("DeviceState is not KSSTATE_RUN or m_Device of CStillPin is NULL!\n");
        return STATUS_UNSUCCESSFUL;
    }

    if (m_Pin->DeviceState != KSSTATE_RUN)
    {
        DBGU_WARNING("Stream State is not KSSTATE_RUN ..\n");
        return STATUS_UNSUCCESSFUL;
    }

    KsPinAcquireProcessingMutex(m_Pin);

    Leading = KsPinGetLeadingEdgeStreamPointer (
                  m_Pin,
                  KSSTREAM_POINTER_STATE_LOCKED
              );

    //
    // Find stream pointer that has Data buffer
    //
    while (NT_SUCCESS (Status) && Leading)
    {
        //
        // If no data is present in the Leading edge stream pointer, just
        // move on to the next frame
        //
        if ( NULL == Leading -> StreamHeader -> Data ) {
            Status = KsStreamPointerAdvance(Leading);
            continue;
        }

        break;
    }

    if (Leading && m_VideoInfoHeader)
    {
        //
        // fill Stream header
        //
        Leading->StreamHeader->DataUsed = 0;
        DBGU_TRACE("buffer Remaining = %d\n",Leading->OffsetOut.Remaining);

        if (Leading->OffsetOut.Remaining >= m_VideoInfoHeader->bmiHeader.biSizeImage)
        {
            Leading -> StreamHeader -> Duration =
                m_VideoInfoHeader -> AvgTimePerFrame;
            Leading -> StreamHeader -> PresentationTime.Numerator =
                Leading -> StreamHeader -> PresentationTime.Denominator = 1;

            Status = m_Device->FrameReadingProcess(
                         m_Pin,
                         Leading->StreamHeader
                     );

            /*// shawn 2011/07/27 for testing +++++
            //
            // Write image data to file.
            //
            IO_STATUS_BLOCK		ioStatusBlock;
            HANDLE				fh;
            LARGE_INTEGER		ByteOffset;
            UNICODE_STRING		uSnapShotFileName;
            OBJECT_ATTRIBUTES	oa;
            UCHAR				p[SNAPSHOT_FILE_HDR_SIZE];
            WCHAR				*wssfn=NULL;

            wssfn = new (NonPagedPool) WCHAR[MAX_PATH];

            //if(!wssfn)
            //	break;

            DBGU_TRACE("Still Process: Start Save Image file! \n");

            swprintf(wssfn, L"\\DosDevices\\C:\\Still_%ws",m_Device->pdx->pVideoDevice->m_SnapShotFileName);
            RtlInitUnicodeString(&uSnapShotFileName, wssfn);
            InitializeObjectAttributes(&oa,&uSnapShotFileName, OBJ_CASE_INSENSITIVE,NULL,NULL);

            if (NT_SUCCESS(ZwCreateFile(	&fh,
            							GENERIC_WRITE | SYNCHRONIZE,
            							&oa,
            							&ioStatusBlock,
            							0,
            							FILE_ATTRIBUTE_NORMAL,
            							FILE_SHARE_WRITE,
            							FILE_OVERWRITE_IF,
            							FILE_SYNCHRONOUS_IO_NONALERT,
            							NULL,
            							0)))
            {
            	ByteOffset.QuadPart = 0;

            	ZwWriteFile(fh,
            				NULL,
            				NULL,
            				NULL,
            				&ioStatusBlock,
            				Leading->StreamHeader->Data,
            				Leading->StreamHeader->DataUsed,
            				&ByteOffset,
            				NULL);

            	ZwClose(fh);
            }//zwCreateFile is ok

            if (wssfn)
            	delete wssfn;
            // shawn 2011/07/27 for testing -----*/

            // shawn 2011/07/28 remove for fixing method 2 MJPEG snapshot issue
            /*if (m_Clock) {
            	LONGLONG ClockTime = m_Clock -> GetTime ();
            	Leading -> StreamHeader -> PresentationTime.Time = ClockTime;
            	Leading -> StreamHeader -> OptionsFlags |=
            		KSSTREAM_HEADER_OPTIONSF_FLUSHONPAUSE |
            		KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
            		KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
            } else*/ {
                //
                // If there is no clock, don't time stamp the packets.
                //
                Leading -> StreamHeader -> PresentationTime.Time = 0;
                Leading -> StreamHeader -> OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_FLUSHONPAUSE;
            }

            //
            // Advances StreamPointer the specified number of bytes into the stream
            // and unlocks it.
            //
            KsStreamPointerAdvanceOffsetsAndUnlock(
                Leading,
                0,
                /*m_VideoInfoHeader->bmiHeader.biSizeImage*/Leading->StreamHeader->DataUsed,
                TRUE
            );
        }
        else
        {
            KeDelay(33);
            KsStreamPointerUnlock(Leading, FALSE);
            Status = STATUS_BUFFER_OVERFLOW;
        }
    }
    //
    // Turn Off the PinGate to avoid processing
    //
    PKSGATE pGate = KsPinGetAndGate(m_Pin);
    if (pGate)
    {
        KsGateTurnInputOff(pGate);
    }

    KsPinReleaseProcessingMutex(m_Pin);

    SnPrint(DEBUGLVL_VERBOSE, ("Leave CStillPin::Process (0x%X)\n",Status));
    return Status;
}
Ejemplo n.º 3
0
NTSTATUS
CEncoderPin::
Process (
)

/*++

Routine Description:

    The process dispatch for the pin bridges to this location.
    We handle setting up scatter gather mappings, etc...

Arguments:

    None

Return Value:

    Success / Failure

--*/

{

    PAGED_CODE();

    NTSTATUS Status = STATUS_SUCCESS;
    PKSSTREAM_POINTER Leading;

    Leading = KsPinGetLeadingEdgeStreamPointer (
                  m_Pin,
                  KSSTREAM_POINTER_STATE_LOCKED
              );

    while (NT_SUCCESS (Status) && Leading) {

        PKSSTREAM_POINTER ClonePointer;
        PSTREAM_POINTER_CONTEXT SPContext;

        //
        // For optimization sake in this particular sample, I will only keep
        // one clone stream pointer per frame.  This complicates the logic
        // here but simplifies the completions.
        //
        // I'm also choosing to do this since I need to keep track of the
        // virtual addresses corresponding to each mapping since I'm faking
        // DMA.  It simplifies that too.
        //
        if (!m_PreviousStreamPointer) {
            //
            // First thing we need to do is clone the leading edge.  This allows
            // us to keep reference on the frames while they're in DMA.
            //
            Status = KsStreamPointerClone (
                         Leading,
                         NULL,
                         sizeof (STREAM_POINTER_CONTEXT),
                         &ClonePointer
                     );

            //
            // I use this for easy chunking of the buffer.  We're not really
            // dealing with physical addresses.  This keeps track of what
            // virtual address in the buffer the current scatter / gather
            // mapping corresponds to for the fake hardware.
            //
            if (NT_SUCCESS (Status)) {

                //
                // Set the stream header data used to 0.  We update this
                // in the DMA completions.  For queues with DMA, we must
                // update this field ourselves.
                //
                ClonePointer -> StreamHeader -> DataUsed = 0;

                SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
                            (ClonePointer -> Context);

                SPContext -> BufferVirtual =
                    reinterpret_cast <PUCHAR> (
                        ClonePointer -> StreamHeader -> Data
                    );
            } else {
                SPContext = NULL;
            }

        } else {

            ClonePointer = m_PreviousStreamPointer;
            SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
                        (ClonePointer -> Context);
            Status = STATUS_SUCCESS;
        }

        //
        // If the clone failed, likely we're out of resources.  Break out
        // of the loop for now.  We may end up starving DMA.
        //
        if (!NT_SUCCESS (Status) || SPContext == NULL) {
            KsStreamPointerUnlock (Leading, FALSE);
            break;
        }

        //
        // Program the fake hardware.  I would use Clone -> OffsetOut.*, but
        // because of the optimization of one stream pointer per frame, it
        // doesn't make complete sense.
        //
        ULONG MappingsUsed =
            m_Device -> ProgramScatterGatherMappings (
                &(SPContext -> BufferVirtual),
                Leading -> OffsetOut.Mappings,
                Leading -> OffsetOut.Remaining
            );

        //
        // In order to keep one clone per frame and simplify the fake DMA
        // logic, make a check to see if we completely used the mappings in
        // the leading edge.  Set a flag.
        //
        if (MappingsUsed == Leading -> OffsetOut.Remaining) {
            m_PreviousStreamPointer = NULL;
        } else {
            m_PreviousStreamPointer = ClonePointer;
        }

        if (MappingsUsed) {
            //
            // If any mappings were added to scatter / gather queues,
            // advance the leading edge by that number of mappings.  If
            // we run off the end of the queue, Status will be
            // STATUS_DEVICE_NOT_READY.  Otherwise, the leading edge will
            // point to a new frame.  The previous one will not have been
            // dismissed (unless "DMA" completed) since there's a clone
            // pointer referencing the frames.
            //
            Status =
                KsStreamPointerAdvanceOffsets (
                    Leading,
                    0,
                    MappingsUsed,
                    FALSE
                );
        } else {

            //
            // The hardware was incapable of adding more entries.  The S/G
            // table is full.
            //
            Status = STATUS_PENDING;
            break;

        }

    }

    //
    // If the leading edge failed to lock (this is always possible, remember
    // that locking CAN occassionally fail), don't blow up passing NULL
    // into KsStreamPointerUnlock.  Also, set m_PendIo to kick us later...
    //
    if (!Leading) {

        m_PendIo = TRUE;

        //
        // If the lock failed, there's no point in getting called back
        // immediately.  The lock could fail due to insufficient memory,
        // etc...  In this case, we don't want to get called back immediately.
        // Return pending.  The m_PendIo flag will cause us to get kicked
        // later.
        //
        Status = STATUS_PENDING;
    }

    //
    // If we didn't run the leading edge off the end of the queue, unlock it.
    //
    if (NT_SUCCESS (Status) && Leading) {
        KsStreamPointerUnlock (Leading, FALSE);
    } else {
        //
        // DEVICE_NOT_READY indicates that the advancement ran off the end
        // of the queue.  We couldn't lock the leading edge.
        //
        if (Status == STATUS_DEVICE_NOT_READY) Status = STATUS_SUCCESS;
    }

    //
    // If we failed with something that requires pending, set the pending I/O
    // flag so we know we need to start it again in a completion DPC.
    //
    if (!NT_SUCCESS (Status) || Status == STATUS_PENDING) {
        m_PendIo = TRUE;
    }

    return Status;

}