Leaked source code of windows server 2003
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

// $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