You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1177 lines
36 KiB
1177 lines
36 KiB
// $Header: G:/SwDev/WDM/Video/bt848/rcs/Capvideo.c 1.11 1998/05/08 00:11:02 tomz Exp $
|
|
|
|
//==========================================================================;
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
// PURPOSE.
|
|
//
|
|
// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//==========================================================================;
|
|
|
|
extern "C" {
|
|
#include "strmini.h"
|
|
#include "ksmedia.h"
|
|
#include "ddkmapi.h"
|
|
}
|
|
|
|
#include "capdebug.h"
|
|
#include "device.h"
|
|
#include "capmain.h"
|
|
|
|
#define DD_OK 0
|
|
|
|
ErrorCode VerifyVideoStream( const KS_DATAFORMAT_VIDEOINFOHEADER &vidHDR );
|
|
ErrorCode VerifyVideoStream2( const KS_DATAFORMAT_VIDEOINFOHEADER2 &vidHDR );
|
|
ErrorCode VerifyVBIStream( const KS_DATAFORMAT_VBIINFOHEADER &rKSDataFormat );
|
|
|
|
void CheckSrbStatus( PHW_STREAM_REQUEST_BLOCK pSrb );
|
|
|
|
// notify class we are ready to rock
|
|
void STREAMAPI StreamCompleterData( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("StreamCompleterData()");
|
|
|
|
DebugOut((1, "*** 1 *** completing SRB %x\n", pSrb));
|
|
CheckSrbStatus( pSrb );
|
|
StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb );
|
|
StreamClassStreamNotification( ReadyForNextStreamDataRequest, pSrb->StreamObject );
|
|
}
|
|
|
|
// notify class we are ready to rock
|
|
void STREAMAPI StreamCompleterControl( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("StreamCompleterControl()");
|
|
|
|
CheckSrbStatus( pSrb );
|
|
StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb );
|
|
StreamClassStreamNotification( ReadyForNextStreamControlRequest, pSrb->StreamObject );
|
|
}
|
|
|
|
/* Function: ProposeDataFormat
|
|
* Purpose: Verifies that data format can be supported
|
|
* Input: SRB
|
|
*/
|
|
void ProposeDataFormat( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("ProposeDataFormat()");
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
|
|
|
|
if ( StreamNumber == STREAM_IDX_VBI ) {
|
|
const KS_DATAFORMAT_VBIINFOHEADER &rKSVBIDataFormat =
|
|
*(PKS_DATAFORMAT_VBIINFOHEADER) pSrb->CommandData.OpenFormat;
|
|
if ( VerifyVBIStream( rKSVBIDataFormat ) != Success )
|
|
pSrb->Status = STATUS_INVALID_PARAMETER;
|
|
return;
|
|
}
|
|
const KS_DATAFORMAT_VIDEOINFOHEADER &rKSDataFormat =
|
|
*(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
|
|
const KS_DATAFORMAT_VIDEOINFOHEADER2 &rKSDataFormat2 =
|
|
*(PKS_DATAFORMAT_VIDEOINFOHEADER2) pSrb->CommandData.OpenFormat;
|
|
|
|
DebugOut((1, "Proposed Data format\n"));
|
|
if ( VerifyVideoStream( rKSDataFormat ) != Success )
|
|
{
|
|
if ( VerifyVideoStream2( rKSDataFormat2 ) != Success )
|
|
{
|
|
pSrb->Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
pSrb->ActualBytesTransferred = sizeof( KS_DATAFORMAT_VIDEOINFOHEADER2 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSrb->ActualBytesTransferred = sizeof( KS_DATAFORMAT_VIDEOINFOHEADER );
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
Data Packet Handling Routines
|
|
|
|
***************************************************************************/
|
|
|
|
/*
|
|
** VideoReceiveDataPacket()
|
|
**
|
|
** Receives Video data packet commands
|
|
**
|
|
** Arguments:
|
|
**
|
|
** pSrb - Stream request block for the Video device
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
|
|
void MockStampVBI( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
|
|
|
|
pDataPacket->PresentationTime.Numerator = 1;
|
|
pDataPacket->PresentationTime.Denominator = 1;
|
|
|
|
pDataPacket->OptionsFlags &= ~KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
|
|
pDataPacket->OptionsFlags &= ~KSSTREAM_HEADER_OPTIONSF_TIMEVALID;
|
|
pDataPacket->OptionsFlags &= ~KS_VBI_FLAG_TVTUNER_CHANGE;
|
|
pDataPacket->OptionsFlags &= ~KS_VBI_FLAG_VBIINFOHEADER_CHANGE;
|
|
pDataPacket->PresentationTime.Time = 0;
|
|
pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
|
|
CheckSrbStatus( pSrb );
|
|
StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb );
|
|
}
|
|
|
|
VOID STREAMAPI VideoReceiveDataPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("VideoReceiveDataPacket()");
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
|
|
|
|
//
|
|
// make sure we have a device extension
|
|
//
|
|
DEBUG_ASSERT((ULONG)adapter);
|
|
|
|
// default to success
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
|
|
//
|
|
// determine the type of packet.
|
|
//
|
|
|
|
DebugOut((1, "VideoReceiveDataPacket(%x) cmd(%x)\n", pSrb, pSrb->Command));
|
|
|
|
switch ( pSrb->Command ) {
|
|
case SRB_READ_DATA:
|
|
//
|
|
// remember the current srb
|
|
//
|
|
DebugOut((1, "PsDevice::VideoReceiveDataPacket - SRB_READ_DATA\n"));
|
|
chan->SetSRB( pSrb );
|
|
adapter->AddBuffer( *chan, pSrb );
|
|
break;
|
|
default:
|
|
//
|
|
// invalid / unsupported command. Fail it as such
|
|
//
|
|
DebugOut((1, "PsDevice::VideoReceiveDataPacket - unknown command(%x)\n", pSrb->Command));
|
|
pSrb->Status = STATUS_NOT_IMPLEMENTED;
|
|
StreamCompleterData( pSrb );
|
|
}
|
|
}
|
|
|
|
/*
|
|
** VideoReceiveCtrlPacket()
|
|
**
|
|
** Receives packet commands that control the Video stream
|
|
**
|
|
** Arguments:
|
|
**
|
|
** pSrb - The stream request block for the Video stream
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
|
|
VOID STREAMAPI VideoReceiveCtrlPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("VideoReceiveCtrlPacket()");
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
DEBUG_ASSERT((ULONG)adapter);
|
|
|
|
// default to success
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
//
|
|
// determine the type of packet.
|
|
//
|
|
|
|
DebugOut((1, "VideoReceiveCtrlPacket(%x) cmd(%x)\n", pSrb, pSrb->Command));
|
|
|
|
int Command = pSrb->Command;
|
|
switch ( Command ) {
|
|
case SRB_SET_STREAM_STATE:
|
|
adapter->SetVideoState( pSrb );
|
|
break;
|
|
case SRB_GET_STREAM_STATE:
|
|
adapter->GetVideoState( pSrb );
|
|
break;
|
|
case SRB_PROPOSE_DATA_FORMAT:
|
|
DebugOut((1, "Propose Data Format\n"));
|
|
ProposeDataFormat( pSrb );
|
|
break;
|
|
|
|
case SRB_SET_DATA_FORMAT:
|
|
DebugOut((1, "Set Data Format\n"));
|
|
// should re-validate just in case ?
|
|
adapter->ProcessSetDataFormat( pSrb );
|
|
break;
|
|
|
|
case SRB_GET_STREAM_PROPERTY:
|
|
adapter->GetStreamProperty( pSrb );
|
|
break;
|
|
case SRB_SET_STREAM_PROPERTY:
|
|
DebugOut(( 0, "SRB_SET_STREAM_PROPERTY\n" ));
|
|
break;
|
|
/*
|
|
case SRB_OPEN_MASTER_CLOCK:
|
|
case SRB_CLOSE_MASTER_CLOCK:
|
|
//
|
|
// This stream is being selected to provide a Master clock
|
|
//
|
|
adapter->SetClockMaster( pSrb );
|
|
break;
|
|
*/
|
|
case SRB_INDICATE_MASTER_CLOCK:
|
|
//
|
|
// Assigns a clock to a stream
|
|
//
|
|
adapter->SetClockMaster( pSrb );
|
|
break;
|
|
default:
|
|
|
|
//
|
|
// invalid / unsupported command. Fail it as such
|
|
//
|
|
|
|
pSrb->Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
if ( Command != SRB_SET_STREAM_STATE &&
|
|
Command != SRB_SET_STREAM_PROPERTY &&
|
|
Command != SRB_SET_DATA_FORMAT )
|
|
StreamCompleterControl( pSrb );
|
|
}
|
|
|
|
/*
|
|
** GetVideoState()
|
|
**
|
|
** Gets the current state of the requested stream
|
|
**
|
|
** Arguments:
|
|
**
|
|
** pSrb - pointer to the stream request block for properties
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
|
|
VOID PsDevice::GetVideoState( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::GetVideoState()");
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
|
|
pSrb->CommandData.StreamState = chan->GetKSState();
|
|
pSrb->ActualBytesTransferred = sizeof (KSSTATE);
|
|
|
|
// A very odd rule:
|
|
// When transitioning from stop to pause, DShow tries to preroll
|
|
// the graph. Capture sources can't preroll, and indicate this
|
|
// by returning VFW_S_CANT_CUE in user mode. To indicate this
|
|
// condition from drivers, they must return ERROR_NO_DATA_DETECTED
|
|
//
|
|
// [TMZ] JayBo says KSSTATE_ACQUIRE should return success
|
|
|
|
if (pSrb->CommandData.StreamState == KSSTATE_PAUSE) {
|
|
pSrb->Status = STATUS_NO_DATA_DETECTED;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** SetVideoState()
|
|
**
|
|
** Sets the current state of the requested stream
|
|
**
|
|
** Arguments:
|
|
**
|
|
** pSrb - pointer to the stream request block for properties
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
|
|
VOID PrintState(StreamState st)
|
|
{
|
|
switch( st ) {
|
|
case Started:
|
|
DebugOut((1, "*** Streamstate was STARTED\n"));
|
|
break;
|
|
case Created:
|
|
DebugOut((1, "*** Streamstate was CREATED\n"));
|
|
break;
|
|
case Paused:
|
|
DebugOut((1, "*** Streamstate was PAUSED\n"));
|
|
break;
|
|
case Open:
|
|
DebugOut((1, "*** Streamstate was OPEN\n"));
|
|
break;
|
|
default:
|
|
DebugOut((1, "*** Streamstate was ??? (%x)\n", st));
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID PsDevice::SetVideoState( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::SetVideoState()");
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
|
|
|
|
//
|
|
// determine which new state is requested
|
|
//
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
chan->SetKSState( pSrb->CommandData.StreamState );
|
|
|
|
switch ( pSrb->CommandData.StreamState ) {
|
|
case KSSTATE_ACQUIRE: // Documented as "same as pause for most minidrivers"
|
|
DebugOut((1, "*** KSSTATE_ACQUIRE(%d) state(%d) falling through to PAUSE\n", StreamNumber, chan->GetState()));
|
|
case KSSTATE_PAUSE:
|
|
// PrintState(chan->GetState());
|
|
|
|
DebugOut((1, "*** KSSTATE_PAUSE(%d) state(%d)\n", StreamNumber, chan->GetState()));
|
|
|
|
switch ( chan->GetState() ) {
|
|
case Started:
|
|
if ( StreamNumber == 2 )
|
|
{
|
|
DebugOut((1, "#############################################################\n"));
|
|
DebugOut((1, "About to pause channel %d\n", StreamNumber ));
|
|
//adapter->CaptureContrll_.DumpRiscPrograms();
|
|
}
|
|
|
|
Pause( *chan ); // intentional fall-through
|
|
|
|
if ( StreamNumber == 2 )
|
|
{
|
|
DebugOut((1, "Done pausing channel %d\n", StreamNumber ));
|
|
DebugOut((1, "#############################################################\n"));
|
|
//adapter->CaptureContrll_.DumpRiscPrograms();
|
|
}
|
|
case Created:
|
|
case Paused: // 2 PAUSE in a row; ignore
|
|
StreamCompleterControl( pSrb );
|
|
break;
|
|
case Open:
|
|
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, Low,
|
|
PHW_PRIORITY_ROUTINE( CreateVideo ), pSrb );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case KSSTATE_STOP:
|
|
// PrintState(chan->GetState());
|
|
|
|
DebugOut((1, "*** KSSTATE_STOP(%d) state(%d)\n", StreamNumber, chan->GetState()));
|
|
|
|
//
|
|
// stop the video
|
|
//
|
|
switch ( chan->GetState() ) {
|
|
default:
|
|
if ( StreamNumber == 2 )
|
|
{
|
|
DebugOut((1, "'#############################################################\n"));
|
|
DebugOut((1, "'About to pause channel %d\n", StreamNumber ));
|
|
//adapter->CaptureContrll_.DumpRiscPrograms();
|
|
}
|
|
|
|
Pause( *chan ); // intentional fall-through
|
|
|
|
if ( StreamNumber == 2 )
|
|
{
|
|
DebugOut((1, "'Done pausing channel %d\n", StreamNumber ));
|
|
DebugOut((1, "'#############################################################\n"));
|
|
//adapter->CaptureContrll_.DumpRiscPrograms();
|
|
}
|
|
case Paused:
|
|
case Created:
|
|
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, Low,
|
|
PHW_PRIORITY_ROUTINE( DestroyVideo ), pSrb );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case KSSTATE_RUN: {
|
|
// PrintState(chan->GetState());
|
|
{
|
|
VideoStream nStreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
|
|
DebugOut((1, "*** KSSTATE_RUN(%d)\n", nStreamNumber));
|
|
}
|
|
|
|
//
|
|
// play the video
|
|
//
|
|
StreamState st = chan->GetState();
|
|
if ( st != Created && st != Paused ) {
|
|
DebugOut((1, "*** KSSTATE_RUN Error (st == %d)\n", st));
|
|
pSrb->Status = STATUS_IO_DEVICE_ERROR;
|
|
} else {
|
|
Start( *chan );
|
|
}
|
|
|
|
StreamCompleterControl( pSrb );
|
|
}
|
|
break;
|
|
default:
|
|
DebugOut((0, "*** KSSTATE_??? (%x)\n", pSrb->CommandData.StreamState));
|
|
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
StreamCompleterControl( pSrb );
|
|
break;
|
|
}
|
|
// when going to paused mode from open and stopping, notification is done in callback
|
|
}
|
|
|
|
/* Method: PsDevice::StartVideo
|
|
* Purpose: Starts a stream
|
|
* Input: pSrb
|
|
*/
|
|
void STREAMAPI PsDevice::StartVideo( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::StartVideo()");
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
// restart the stream
|
|
adapter->Start( *chan );
|
|
adapter->Pause( *chan );
|
|
|
|
// finally, can complete the SET dataformat SRB
|
|
// StreamCompleterControl( pSrb );
|
|
|
|
// cannot call any other class' services; have to schedule a callback
|
|
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh,
|
|
PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb );
|
|
}
|
|
|
|
/* Method: PsDevice::CreateVideo
|
|
* Purpose: Starts a stream
|
|
* Input: pSrb
|
|
*/
|
|
void STREAMAPI PsDevice::CreateVideo( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::CreateVideo()");
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
if ( adapter->Create( *chan ) != Success )
|
|
pSrb->Status = STATUS_IO_DEVICE_ERROR;
|
|
|
|
// cannot call any other class' services; have to schedule a callback
|
|
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh,
|
|
PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb );
|
|
}
|
|
|
|
/* Method: PsDevice::DestroyVideo
|
|
* Purpose: Called at low priority to stop video and free the resources
|
|
*/
|
|
void STREAMAPI PsDevice::DestroyVideoNoComplete( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::DestroyVideoNoComplete()");
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
// have all resources freed
|
|
adapter->Stop( *chan );
|
|
|
|
// set new format
|
|
KS_DATAFORMAT_VIDEOINFOHEADER &rDataVideoInfHdr =
|
|
*(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
|
|
KS_DATAFORMAT_VIDEOINFOHEADER2 &rDataVideoInfHdr2 =
|
|
*(PKS_DATAFORMAT_VIDEOINFOHEADER2) pSrb->CommandData.OpenFormat;
|
|
|
|
if ( IsEqualGUID( rDataVideoInfHdr.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) )
|
|
{
|
|
chan->SetVidHdr( rDataVideoInfHdr.VideoInfoHeader );
|
|
}
|
|
else
|
|
{
|
|
chan->SetVidHdr2( rDataVideoInfHdr2.VideoInfoHeader2 );
|
|
}
|
|
|
|
// re-create the stream
|
|
if ( adapter->Create( *chan ) != Success ) {
|
|
pSrb->Status = STATUS_IO_DEVICE_ERROR;
|
|
StreamCompleterControl( pSrb );
|
|
} else {
|
|
|
|
DebugOut((1, "1 pSrb = %lx\n", pSrb));
|
|
DebugOut((1, "1 pSrb->StreamObject = %lx\n", pSrb->StreamObject));
|
|
DebugOut((1, "1 chan = %lx\n", chan));
|
|
DebugOut((1, "1 HwStreamExtension = %lx\n", pSrb->StreamObject->HwStreamExtension));
|
|
|
|
// we're already at low priority ???
|
|
// StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, Low,
|
|
// PHW_PRIORITY_ROUTINE( StartVideo ), pSrb );
|
|
// StartVideo( pSrb);
|
|
|
|
// cannot call any other class' services; have to schedule a callback
|
|
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh,
|
|
PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb );
|
|
}
|
|
}
|
|
|
|
/* Method: PsDevice::DestroyVideo
|
|
* Purpose: Called at low priority to stop video and free the resources
|
|
*/
|
|
void STREAMAPI PsDevice::DestroyVideo( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::DestroyVideo()");
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
adapter->Stop( *chan );
|
|
|
|
// cannot call any other class' services; have to schedule a callback
|
|
StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh,
|
|
PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb );
|
|
}
|
|
|
|
/*
|
|
** VideoGetProperty()
|
|
**
|
|
** Routine to process video property requests
|
|
**
|
|
** Arguments:
|
|
**
|
|
** pSrb - pointer to the stream request block for properties
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
void PsDevice::GetStreamProperty( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::GetStreamProperty()");
|
|
|
|
PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
|
|
|
|
if ( IsEqualGUID( KSPROPSETID_Connection, pSPD->Property->Set ) ) {
|
|
GetStreamConnectionProperty( pSrb );
|
|
} else {
|
|
pSrb->Status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
/* Method: PsDevice::ProcessSetDataFormat
|
|
* Purpose: Implements SET KSPROPERTY_CONNECTION_DATAFORMAT
|
|
* Input: chan: VideoChannel &
|
|
* VidInfHdr: KS_VIDEOINFOHEADER &
|
|
*/
|
|
void PsDevice::ProcessSetDataFormat( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::ProcessSetDataFormat()");
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
// have to stop first
|
|
Pause( *chan );
|
|
|
|
// destroy at low prioriy
|
|
StreamClassCallAtNewPriority( pSrb->StreamObject, pSrb->HwDeviceExtension, Low,
|
|
PHW_PRIORITY_ROUTINE( DestroyVideoNoComplete ), pSrb );
|
|
}
|
|
|
|
/* Method: PsDevice::GetStreamConnectionProperty
|
|
* Purpose: Obtains allocator and state properties
|
|
*/
|
|
void PsDevice::GetStreamConnectionProperty( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::GetStreamConnectionProperty()");
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
|
|
ULONG Id = pSPD->Property->Id; // index of the property
|
|
|
|
switch ( Id ) {
|
|
case KSPROPERTY_CONNECTION_ALLOCATORFRAMING: {
|
|
|
|
|
|
//KdPrint(( "KSPROPERTY_CONNECTION_ALLOCATORFRAMING\n" ));
|
|
|
|
|
|
PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
|
|
Framing->RequirementsFlags =
|
|
KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY |
|
|
KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
|
|
KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY;
|
|
Framing->PoolType = NonPagedPool;
|
|
|
|
//KdPrint(( "Framing->Frames == 0x%08X\n", Framing->Frames ));
|
|
if( (VideoStream)pSrb->StreamObject->StreamNumber == STREAM_IDX_VBI )
|
|
{
|
|
Framing->Frames = 8;
|
|
}
|
|
else
|
|
{
|
|
//if( Framing->Frames == 0 )
|
|
//{
|
|
// Framing->Frames = 1;
|
|
//}
|
|
//else
|
|
//{
|
|
Framing->Frames = 3;
|
|
//}
|
|
}
|
|
if( chan->IsVideoInfo2() )
|
|
{
|
|
Framing->FrameSize = chan->GetVidHdr2()->bmiHeader.biSizeImage;
|
|
}
|
|
else
|
|
{
|
|
Framing->FrameSize = chan->GetVidHdr()->bmiHeader.biSizeImage;
|
|
}
|
|
Framing->FileAlignment = 0;//FILE_QUAD_ALIGNMENT;// PAGE_SIZE - 1;
|
|
Framing->Reserved = 0;
|
|
pSrb->ActualBytesTransferred = sizeof( KSALLOCATOR_FRAMING );
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void PsDevice::SetClockMaster( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("PsDevice::SetClockMaster()");
|
|
|
|
VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
chan->SetClockMaster( pSrb->CommandData.MasterClockHandle );
|
|
}
|
|
|
|
/* Method: AnalogReceiveDataPacket
|
|
* Purpose: Receives data packets for analog stream ( tuner change notifications )
|
|
* Input: SRB
|
|
*/
|
|
VOID STREAMAPI AnalogReceiveDataPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("AnalogReceiveDataPacket()");
|
|
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension =
|
|
(PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
|
|
|
|
PsDevice *adapter = HwDeviceExtension->psdevice;
|
|
|
|
DebugOut((1, "AnalogReceiveDataPacket(%x) cmd(%x)\n", pSrb, pSrb->Command));
|
|
|
|
switch ( pSrb->Command ) {
|
|
case SRB_READ_DATA:
|
|
break;
|
|
case SRB_WRITE_DATA:
|
|
//
|
|
// This data packet contains the channel change information
|
|
// passed on the AnalogVideoIn
|
|
//
|
|
if ( pSrb->CommandData.DataBufferArray->FrameExtent ==
|
|
sizeof( KS_TVTUNER_CHANGE_INFO ) )
|
|
adapter->ChangeNotifyChannels( pSrb );
|
|
break;
|
|
default:
|
|
//
|
|
// invalid / unsupported command. Fail it as such
|
|
//
|
|
pSrb->Status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
StreamCompleterData( pSrb );
|
|
}
|
|
|
|
/* Method: AnalogReceiveCtrlPacket
|
|
* Purpose: Receives control packets for analog stream ( are there any ? )
|
|
* Input: SRB
|
|
*/
|
|
VOID STREAMAPI AnalogReceiveCtrlPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
Trace t("AnalogReceiveCtrlPacket()");
|
|
|
|
DebugOut((1, "AnalogReceiveCtrlPacket(%x) cmd(%x)\n", pSrb, pSrb->Command));
|
|
|
|
pSrb->Status = STATUS_SUCCESS;
|
|
StreamCompleterControl( pSrb );
|
|
}
|
|
|
|
|
|
#ifdef ENABLE_DDRAW_STUFF
|
|
|
|
DWORD FAR PASCAL
|
|
DirectDrawEventCallback( DWORD dwEvent, PVOID pContext, DWORD dwParam1, DWORD dwParam2 )
|
|
{
|
|
switch( dwEvent )
|
|
{
|
|
case DDNOTIFY_PRERESCHANGE:
|
|
{
|
|
VideoChannel* pChan = (VideoChannel*)pContext;
|
|
KdPrint(( "DDNOTIFY_PRERESCHANGE; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber ));
|
|
pChan->bPreEventOccurred = TRUE;
|
|
}
|
|
break;
|
|
case DDNOTIFY_POSTRESCHANGE:
|
|
{
|
|
VideoChannel* pChan = (VideoChannel*)pContext;
|
|
KdPrint(( "DDNOTIFY_POSTRESCHANGE; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber ));
|
|
pChan->bPostEventOccurred = TRUE;
|
|
KdPrint(( "before Attempted Renegotiation due to DDNOTIFY_POSTRESCHANGE\n" ));
|
|
// AttemptRenegotiation(pStrmEx);
|
|
KdPrint(( "after Attempted Renegotiation due to DDNOTIFY_POSTRESCHANGE\n" ));
|
|
}
|
|
break;
|
|
case DDNOTIFY_PREDOSBOX:
|
|
{
|
|
VideoChannel* pChan = (VideoChannel*)pContext;
|
|
KdPrint(( "DDNOTIFY_PREDOSBOX; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber ));
|
|
pChan->bPreEventOccurred = TRUE;
|
|
}
|
|
break;
|
|
case DDNOTIFY_POSTDOSBOX:
|
|
{
|
|
VideoChannel* pChan = (VideoChannel*)pContext;
|
|
KdPrint(( "DDNOTIFY_POSTDOSBOX; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber ));
|
|
pChan->bPostEventOccurred = TRUE;
|
|
KdPrint(( "before Attempted Renegotiation due to DDNOTIFY_POSTDOSBOX\n" ));
|
|
// AttemptRenegotiation(pStrmEx);
|
|
KdPrint(( "after Attempted Renegotiation due to DDNOTIFY_POSTDOSBOX\n" ));
|
|
}
|
|
break;
|
|
case DDNOTIFY_CLOSEDIRECTDRAW:
|
|
{
|
|
VideoChannel* pChan = (VideoChannel*)pContext;
|
|
KdPrint(( "DDNOTIFY_CLOSEDIRECTDRAW\n" ));
|
|
pChan->hKernelDirectDrawHandle = 0;
|
|
pChan->hUserDirectDrawHandle = 0;
|
|
}
|
|
break;
|
|
case DDNOTIFY_CLOSESURFACE:
|
|
{
|
|
VideoChannel* pChan = (VideoChannel*)pContext;
|
|
PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pChan->pSRB_->SRBExtension;
|
|
KdPrint(( "DDNOTIFY_CLOSESURFACE\n" ));
|
|
pSrbExt->hKernelSurfaceHandle = 0;
|
|
}
|
|
break;
|
|
default:
|
|
KdPrint(( "unknown/unhandled ddraw event\n" ));
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL RegisterForDirectDrawEvents( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
|
|
DDREGISTERCALLBACK ddRegisterCallback;
|
|
DWORD ddOut;
|
|
VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
KdPrint(( "stream %d registering for DirectDraw events\n", pSrb->StreamObject->StreamNumber ));
|
|
|
|
// =============== DDEVENT_PRERESCHANGE ===============
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_PRERESCHANGE;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
// =============== DDEVENT_POSTRESCHANGE ==============
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_POSTRESCHANGE;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi(DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
// =============== DDEVENT_PREDOSBOX =================
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_PREDOSBOX;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
// =============== DDEVENT_POSTDOSBOX ================
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_POSTDOSBOX;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
pChan->bKernelDirectDrawRegistered = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL UnregisterForDirectDrawEvents( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
|
|
DDREGISTERCALLBACK ddRegisterCallback;
|
|
DWORD ddOut;
|
|
VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
KdPrint(( "stream %d un-registering for DirectDraw events\n", pSrb->StreamObject->StreamNumber ));
|
|
|
|
// =============== DDEVENT_PRERESCHANGE ===============
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_PRERESCHANGE;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut));
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
// =============== DDEVENT_POSTRESCHANGE ==============
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_POSTRESCHANGE;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
// =============== DDEVENT_PREDOSBOX ==================
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_PREDOSBOX;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
// =============== DDEVENT_POSTDOSBOX =================
|
|
RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) );
|
|
RtlZeroMemory( &ddOut, sizeof(ddOut) );
|
|
|
|
ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle;
|
|
ddRegisterCallback.dwEvents = DDEVENT_POSTDOSBOX;
|
|
ddRegisterCallback.pfnCallback = DirectDrawEventCallback;
|
|
ddRegisterCallback.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" ));
|
|
return FALSE;
|
|
}
|
|
pChan->bKernelDirectDrawRegistered = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL OpenKernelDirectDraw( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
/*
|
|
VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
|
|
if( pChan->hUserDirectDrawHandle != 0 )
|
|
{
|
|
DDOPENDIRECTDRAWIN ddOpenIn;
|
|
DDOPENDIRECTDRAWOUT ddOpenOut;
|
|
|
|
ASSERT( pChan->hKernelDirectDrawHandle == 0 );
|
|
|
|
KdPrint(( "stream %d getting kernel ddraw handle\n", pSrb->StreamObject->StreamNumber ));
|
|
|
|
RtlZeroMemory( &ddOpenIn, sizeof(ddOpenIn) );
|
|
RtlZeroMemory( &ddOpenOut, sizeof(ddOpenOut) );
|
|
|
|
ddOpenIn.dwDirectDrawHandle = (DWORD)pChan->hUserDirectDrawHandle;
|
|
ddOpenIn.pfnDirectDrawClose = DirectDrawEventCallback;
|
|
ddOpenIn.pContext = pChan;
|
|
|
|
DxApi( DD_DXAPI_OPENDIRECTDRAW, (DWORD)&ddOpenIn, sizeof(ddOpenIn), (DWORD)&ddOpenOut, sizeof(ddOpenOut) );
|
|
|
|
if( ddOpenOut.ddRVal != DD_OK )
|
|
{
|
|
KdPrint(( "DD_DXAPI_OPENDIRECTDRAW failed.\n" ));
|
|
}
|
|
else
|
|
{
|
|
pChan->hKernelDirectDrawHandle = ddOpenOut.hDirectDraw;
|
|
return TRUE;
|
|
}
|
|
}
|
|
*/
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL CloseKernelDirectDraw( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
/*
|
|
if( pChan->hKernelDirectDrawHandle != 0 )
|
|
{
|
|
DWORD ddOut;
|
|
DDCLOSEHANDLE ddClose;
|
|
KdPrint(( "stream %d CloseKernelDirectDraw\n", pSrb->StreamObject->StreamNumber ));
|
|
ddClose.hHandle = pChan->hKernelDirectDrawHandle;
|
|
|
|
DxApi( DD_DXAPI_CLOSEHANDLE, (DWORD)&ddClose, sizeof(ddClose), (DWORD) &ddOut, sizeof(ddOut) );
|
|
|
|
pChan->hKernelDirectDrawHandle = 0;
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
KdPrint(( "CloseKernelDirectDraw FAILED.\n" ));
|
|
return FALSE;
|
|
}
|
|
}
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL IsKernelLockAndFlipAvailable( PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
if( pChan->hKernelDirectDrawHandle != 0 )
|
|
{
|
|
DDGETKERNELCAPSOUT ddGetKernelCapsOut;
|
|
KdPrint(( "stream %d getting Kernel Caps\n", pSrb->StreamObject->StreamNumber ));
|
|
|
|
RtlZeroMemory( &ddGetKernelCapsOut, sizeof(ddGetKernelCapsOut) );
|
|
|
|
DxApi(
|
|
DD_DXAPI_GETKERNELCAPS,
|
|
(DWORD) &pChan->hKernelDirectDrawHandle,
|
|
sizeof(pChan->hKernelDirectDrawHandle),
|
|
(DWORD)&ddGetKernelCapsOut,
|
|
sizeof(ddGetKernelCapsOut)
|
|
);
|
|
|
|
if( ddGetKernelCapsOut.ddRVal != DD_OK )
|
|
{
|
|
//KdPrint(( "DDGETKERNELCAPSOUT failed.\n" ));
|
|
}
|
|
else
|
|
{
|
|
//KdPrint(( "stream %d KernelCaps = %x\n", pSrb->StreamObject->StreamNumber, ddGetKernelCapsOut.dwCaps ));
|
|
// TODO:, check the flags here
|
|
// if (ddGetKernelCapsOut.dwCaps & ???)
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL OpenKernelDDrawSurfaceHandle( IN PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension;
|
|
|
|
ASSERT( pChan->hKernelDirectDrawHandle != 0 );
|
|
ASSERT( pSrbExt->hUserSurfaceHandle != 0 );
|
|
|
|
if( pSrbExt->hUserSurfaceHandle == 0 )
|
|
{
|
|
DDOPENSURFACEIN ddOpenSurfaceIn;
|
|
DDOPENSURFACEOUT ddOpenSurfaceOut;
|
|
|
|
//KdPrint(( "stream %d getting Kernel surface handle\n", pSrb->StreamObject->StreamNumber ));
|
|
|
|
RtlZeroMemory( &ddOpenSurfaceIn, sizeof(ddOpenSurfaceIn) );
|
|
RtlZeroMemory( &ddOpenSurfaceOut, sizeof(ddOpenSurfaceOut) );
|
|
|
|
ddOpenSurfaceIn.hDirectDraw = pChan->hUserDirectDrawHandle;
|
|
ddOpenSurfaceIn.pfnSurfaceClose = DirectDrawEventCallback;
|
|
ddOpenSurfaceIn.pContext = pSrb;
|
|
|
|
ddOpenSurfaceIn.dwSurfaceHandle = (DWORD)pSrbExt->hUserSurfaceHandle;
|
|
|
|
DxApi( DD_DXAPI_OPENSURFACE, (DWORD)&ddOpenSurfaceIn, sizeof(ddOpenSurfaceIn), (DWORD)&ddOpenSurfaceOut, sizeof(ddOpenSurfaceOut) );
|
|
|
|
if( ddOpenSurfaceOut.ddRVal != DD_OK )
|
|
{
|
|
pSrbExt->hKernelSurfaceHandle = 0;
|
|
//KdPrint(( "DD_DXAPI_OPENSURFACE failed.\n" ));
|
|
}
|
|
else
|
|
{
|
|
pSrbExt->hKernelSurfaceHandle = ddOpenSurfaceOut.hSurface;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL CloseKernelDDrawSurfaceHandle( IN PHW_STREAM_REQUEST_BLOCK pSrb )
|
|
{
|
|
VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
|
|
PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension;
|
|
|
|
ASSERT( pChan->hKernelDirectDrawHandle != 0 );
|
|
ASSERT( pSrbExt->hUserSurfaceHandle != 0 );
|
|
ASSERT( pSrbExt->hKernelSurfaceHandle != 0 );
|
|
|
|
if( pSrbExt->hKernelSurfaceHandle != 0 )
|
|
{
|
|
DWORD ddOut;
|
|
DDCLOSEHANDLE ddClose;
|
|
|
|
//KdPrint(( "stream %d ReleaseKernelDDrawSurfaceHandle\n", pSrb->StreamObject->StreamNumber ));
|
|
|
|
ddClose.hHandle = pSrbExt->hKernelSurfaceHandle;
|
|
|
|
DxApi( DD_DXAPI_CLOSEHANDLE, (DWORD)&ddClose, sizeof(ddClose), (DWORD) &ddOut, sizeof(ddOut) );
|
|
|
|
pSrbExt->hKernelSurfaceHandle = 0; // what else can we do?
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
//KdPrint(( "ReleaseKernelDDrawSurfaceHandle() FAILED.\n" ));
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL FlipOverlay( HANDLE hDirectDraw, HANDLE hCurrentSurface, HANDLE hTargetSurface )
|
|
{
|
|
DDFLIPOVERLAY ddFlipOverlay;
|
|
DWORD ddOut;
|
|
|
|
RtlZeroMemory( &ddFlipOverlay, sizeof(ddFlipOverlay) );
|
|
ddFlipOverlay.hDirectDraw = hDirectDraw;
|
|
ddFlipOverlay.hCurrentSurface = hCurrentSurface;
|
|
ddFlipOverlay.hTargetSurface = hTargetSurface;
|
|
ddFlipOverlay.dwFlags = 0;
|
|
|
|
DxApi( DD_DXAPI_FLIP_OVERLAY, (DWORD)&ddFlipOverlay, sizeof(ddFlipOverlay), (DWORD)&ddOut, sizeof(ddOut) );
|
|
|
|
if( ddOut != DD_OK )
|
|
{
|
|
//KdPrint(( "FlipOverlay() FAILED.\n" ));
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|