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.
 
 
 
 
 
 

535 lines
18 KiB

//==========================================================================;
//
// 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.
//
//==========================================================================;
#include "Scaler.h"
#include "capdebug.h"
#include "capmain.h"
#include "defaults.h"
// video information for PAL
VideoInfoStruct NTSCVideoInfo =
{
730, // Clkx1_HACTIVE = 746
148, // Clkx1_HDELAY = 140
44, // Min_Pixels = 44
240, // Active_lines_per_field = 240
144, // Min_UncroppedPixels = Min_Pixels + 100
724, // Max_Pixels = ((Clkx1_HACTIVE < 774) ? Clkx1_HACTIVE - 6 : 768)
32, // Min_Lines = (Active_lines_per_field / 16 + 1) * 2
240, // Max_Lines = Active_lines_per_field
352, // Max_VFilter1_Pixels = ((Clkx1_HACTIVE > 796) ? 384 : (Clkx1_HACTIVE * 14 / 29))
176, // Max_VFilter2_Pixels = Clkx1_HACTIVE * 8 / 33
176, // Max_VFilter3_Pixels = Clkx1_HACTIVE * 8 / 33
240, // Max_VFilter1_Lines = Active_lines_per_field
120, // Max_VFilter2_Lines = Active_lines_per_field / 2
96, // Max_VFilter3_Lines = Active_lines_per_field * 2 / 5
};
// video information for PAL
VideoInfoStruct PALVideoInfo =
{
914, // Clkx1_HACTIVE = 914
190, // Clkx1_HDELAY = 190
48, // Min_Pixels = 48
284, // Active_lines_per_field = 284
148, // Min_UncroppedPixels = Min_Pixels + 100
768, // Max_Pixels = ((Clkx1_HACTIVE < 774) ? Clkx1_HACTIVE - 6 : 768)
36, // Min_Lines = (Active_lines_per_field / 16 + 1) * 2
284, // Max_Lines = Active_lines_per_field
384, // Max_VFilter1_Pixels = ((Clkx1_HACTIVE > 796) ? 384 : (Clkx1_HACTIVE * 14 / 29))
221, // Max_VFilter2_Pixels = Clkx1_HACTIVE * 8 / 33
221, // Max_VFilter3_Pixels = Clkx1_HACTIVE * 8 / 33
284, // Max_VFilter1_Lines = Active_lines_per_field
142, // Max_VFilter2_Lines = Active_lines_per_field / 2
113, // Max_VFilter3_Lines = Active_lines_per_field * 2 / 5
};
//===========================================================================
// Bt848 Scaler Class Implementation
//===========================================================================
/////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////
#define REGALIGNMENT 1
#define offset 0
Scaler::Scaler(PDEVICE_PARMS pDeviceParms):
regCROP ((0x03 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
fieldVACTIVE_MSB(regCROP, 4, 2, RW) ,
fieldHDELAY_MSB(regCROP, 2, 2, RW) ,
fieldHACTIVE_MSB(regCROP, 0, 2, RW) ,
regVACTIVE_LO ((0x05 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
regHDELAY_LO ((0x06 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
regHACTIVE_LO ((0x07 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
regHSCALE_HI ((0x08 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
fieldHSCALE_MSB(regHSCALE_HI, 0, 8, RW) ,
regHSCALE_LO ((0x09 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
regSCLOOP ((0x10 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
fieldHFILT(regSCLOOP, 3, 2, RW) ,
regVSCALE_HI ((0x13 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
fieldVSCALE_MSB(regVSCALE_HI, 0, 5, RW) ,
regVSCALE_LO ((0x14 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
regVActive(regVACTIVE_LO, 8, fieldVACTIVE_MSB, RW),
regVScale(regVSCALE_LO, 8, fieldVSCALE_MSB, RW),
regHDelay(regHDELAY_LO, 8, fieldHDELAY_MSB, RW),
regHActive(regHACTIVE_LO, 8, fieldHACTIVE_MSB, RW),
regHScale(regHSCALE_LO, 8, fieldHSCALE_MSB, RW),
regVTC ((0x1B * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
fieldVBIEN (regVTC, 4, 1, RW),
fieldVBIFMT (regVTC, 3, 1, RW),
fieldVFILT (regVTC, 0, 2, RW),
regReverse_CROP (0x03, RW, pDeviceParms),
fieldVDELAY_MSB(regReverse_CROP, 6, 2, RW),
regVDELAY_LO (0x04, RW, pDeviceParms),
regVDelay(regVDELAY_LO, 8, fieldVDELAY_MSB, RW),
m_videoFormat(VFormat_NTSC), VFilterFlag_(On),
DigitalWin_(0,0,NTSCMaxOutWidth,NTSCMaxOutHeight)
{
m_HActive = 0;
m_pixels = 0;
m_lines = 0;
m_VFilter = 0;
}
/////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////
Scaler::~Scaler()
{
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::VideoFormatChanged(VideoFormat format)
// Purpose: Set which video format is using
// Input: Video format -
// Auto format: VFormat_AutoDetect
// NTSC (M): VFormat_NTSC
// PAL (B, D, G, H, I): VFormat_PAL_BDGHI
// PAL (M): VFormat_PAL_M
// PAL(N): VFormat_PAL_N
// SECAM: VFormat_SECAM
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::VideoFormatChanged(VideoFormat format)
{
m_videoFormat = format;
Scale(DigitalWin_);
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::Scale(MRect & clientScr)
// Purpose: Perform scaling
// Input: MRect & clientScr - rectangle to scale to
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::Scale(MRect & clientScr)
{
switch (m_videoFormat)
{
case VFormat_NTSC:
case VFormat_NTSC_J:
case VFormat_PAL_M:
m_ptrVideoIn = &NTSCVideoInfo; // set scaling constants for NTSC
break;
case VFormat_PAL_BDGHI:
case VFormat_PAL_N:
case VFormat_SECAM:
case VFormat_PAL_N_COMB:
m_ptrVideoIn = &PALVideoInfo; // set scaling constants for PAL/SECAM
if ( m_videoFormat == VFormat_PAL_N_COMB )
{
m_ptrVideoIn->Clkx1_HACTIVE = NTSCVideoInfo.Clkx1_HACTIVE; // p. 26 of BT guide
m_ptrVideoIn->Clkx1_HDELAY = NTSCVideoInfo.Clkx1_HDELAY; // empirical
}
break;
}
// the order of functions calling here is important because some
// calculations are based on previous results
SetHActive(clientScr);
SetVActive();
SetVScale(clientScr);
SetVFilter();
SetVDelay();
SetHDelay();
SetHScale();
SetHFilter();
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetHActive(MRect & clientScr)
// Purpose: Set HActive register
// Input: MRect & clientScr - rectangle to scale to
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetHActive(MRect & clientScr)
{
m_HActive = min(m_ptrVideoIn->Max_Pixels,
max((WORD)clientScr.Width(), m_ptrVideoIn->Min_Pixels));
regHActive = m_HActive;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetHDelay()
// Purpose: Set HDelay register
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetHDelay()
{
// calculations here requires calculation of HActive first!
m_pixels = m_HActive;
if (m_pixels < m_ptrVideoIn->Min_UncroppedPixels)
m_pixels += (WORD) ((m_ptrVideoIn->Min_UncroppedPixels - m_pixels + 9) / 10);
LONG a = (LONG)m_pixels * (LONG)m_ptrVideoIn->Clkx1_HDELAY;
LONG b = (LONG)m_ptrVideoIn->Clkx1_HACTIVE * 2L;
WORD HDelay = (WORD) ((a + (LONG)m_ptrVideoIn->Clkx1_HACTIVE * 2 - 1) / b * 2L);
// now add the cropping region into HDelay register; i.e. skip some pixels
// before we start taking them as real image
HDelay += (WORD)AnalogWin_.left;
// HDelay must be even or else color would be wrong
HDelay &= ~01;
regHDelay = HDelay;
// since we increase HDelay, we should decrease HActive by the same amount
m_HActive -= (WORD)AnalogWin_.left;
regHActive = m_HActive;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetHScale()
// Purpose: Set HScale register
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetHScale()
{
regHScale = (WORD) ((((LONG)m_ptrVideoIn->Clkx1_HACTIVE * 4096L) /
(LONG)m_pixels) - 4096L);
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetHFilter()
// Purpose: Set HFilt register field
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetHFilter()
{
if (m_videoFormat != VFormat_SECAM)
fieldHFILT = HFilter_AutoFormat;
else // SECAM
if (m_pixels < m_ptrVideoIn->Clkx1_HACTIVE / 7)
fieldHFILT = HFilter_ICON;
else
fieldHFILT = HFilter_QCIF;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetVScale(MRect & clientScr)
// Purpose: Set VScale register
// Input: MRect & clientScr - rectangle to scale to
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetVScale(MRect & clientScr)
{
m_lines = min(m_ptrVideoIn->Max_Lines,
max((WORD)clientScr.Height(), m_ptrVideoIn->Min_Lines));
WORD LPB_VScale_Factor = (WORD) (1 + (m_lines - 1) / m_ptrVideoIn->Active_lines_per_field);
m_lines = (WORD) ((m_lines + LPB_VScale_Factor - 1) / LPB_VScale_Factor);
LONG a = (LONG)m_ptrVideoIn->Active_lines_per_field * 512L / (LONG)m_lines;
WORD VScale = (WORD) ((0x10000L - a + 512L) & 0x1FFFL);
regVScale = VScale;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetVDelay()
// Purpose: Set VDelay register
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetVDelay()
{
WORD VDelay, moreDelay;
// increase VDelay will eliminate garbage lines at top of image
switch (m_VFilter)
{
case 3:
moreDelay = 4;
break;
case 2:
moreDelay = 2;
break;
case 1:
case 0:
default:
moreDelay = 0;
break;
}
if ( ( m_videoFormat == VFormat_NTSC ) ||
( m_videoFormat == VFormat_NTSC_J ) ||
( m_videoFormat == VFormat_PAL_M ) ||
( m_videoFormat == VFormat_PAL_N_COMB ) ) // the reason that PAL_N_COMB is here is purely empirical
VDelay = 0x001A + moreDelay; // NTSC
else
VDelay = 0x0026 + moreDelay; // PAL/SECAM
// now add the cropping region into VDelay register; i.e. skip some pixels
// before we start taking them as real image
VDelay += (WORD)(((LONG)m_ptrVideoIn->Max_Lines * (LONG)AnalogWin_.top + m_lines - 1) / (LONG)m_lines * 2);
regVDelay = VDelay;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetVActive()
// Purpose: Set VActive register
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetVActive()
{
// No calculation needed for VActive register since it based on the UNSCALED image
if ( ( m_videoFormat == VFormat_NTSC ) ||
( m_videoFormat == VFormat_NTSC_J ) ||
( m_videoFormat == VFormat_PAL_M ) )
regVActive = 0x1F4;
else
regVActive = 0x238;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetVBIEN(BOOL)
// Purpose: Set VBIEN register field
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetVBIEN(BOOL enable)
{
if (enable)
{
fieldVBIEN = 1;
}
else
{
fieldVBIEN = 0;
}
}
/////////////////////////////////////////////////////////////////////////////
// Method: BOOL void Scaler::IsVBIEN()
// Purpose: Set VBIEN register field
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
BOOL Scaler::IsVBIEN()
{
if (fieldVBIEN)
return TRUE;
else
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetVBIFMT(BOOL)
// Purpose: Set VBIFMT register field
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetVBIFMT(BOOL enable)
{
if (enable)
{
fieldVBIFMT = 1;
}
else
{
fieldVBIFMT = 0;
}
}
/////////////////////////////////////////////////////////////////////////////
// Method: BOOL void Scaler::IsVBIFMT()
// Purpose: Set VBIFMT register field
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
BOOL Scaler::IsVBIFMT()
{
if (fieldVBIFMT)
return TRUE;
else
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::SetVFilter()
// Purpose: Set VFilt register field
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::SetVFilter()
{
// this is to remove junk lines at the top of video. flag set to off
// when image hight is above CIF
if (VFilterFlag_ == Off) {
fieldVFILT = 0;
m_VFilter = 0;
return;
}
if ((m_HActive <= m_ptrVideoIn->Max_VFilter3_Pixels) &&
(m_lines <= m_ptrVideoIn->Max_VFilter3_Lines))
m_VFilter = 3;
else if ((m_HActive <= m_ptrVideoIn->Max_VFilter2_Pixels) &&
(m_lines <= m_ptrVideoIn->Max_VFilter2_Lines))
m_VFilter = 2;
else if ((m_HActive <= m_ptrVideoIn->Max_VFilter1_Pixels) &&
(m_lines <= m_ptrVideoIn->Max_VFilter1_Lines))
m_VFilter = 1;
else
m_VFilter = 0;
fieldVFILT = m_VFilter;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::GetDigitalWin(MRect &DigWin) const
// Purpose: Retreives the size of digital window
// Input: None
// Output: MRect &DigWin - retrieved value
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::GetDigitalWin(MRect &DigWin) const
{
DigWin = DigitalWin_;
}
/////////////////////////////////////////////////////////////////////////////
// Method: ErrorCode Scaler::SetDigitalWin(const MRect &DigWin)
// Purpose: Sets the size and location of the digital window
// Input: const MRect &DigWin - window size to set to
// Output: None
// Return: Success or Fail if passed rect is bigger then analog window
// Note: This function can affect the scaling, so Scale() is called
/////////////////////////////////////////////////////////////////////////////
ErrorCode Scaler::SetDigitalWin(const MRect &DigWin)
{
// we can not scale up
if ((DigWin.Height() > AnalogWin_.Height()) ||
(DigWin.Width() > AnalogWin_.Width()))
return Fail;
DigitalWin_ = DigWin;
// every invocation of SetDigitalWin potentially changes the scaling
Scale(DigitalWin_);
return Success;
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Scaler::GetAnalogWin(MRect &AWin) const
// Purpose: Retreives the size of analog window
// Input: None
// Output: MRect &DigWin - retrieved value
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Scaler::GetAnalogWin(MRect &AWin) const
{
AWin = AnalogWin_;
}
/////////////////////////////////////////////////////////////////////////////
// Method: ErrorCode Scaler::SetAnalogWin(const MRect &AWin)
// Purpose: Sets the size and location of the analog window
// Input: const MRect &AWin - window size to set to
// Output: None
// Return: Success or Fail if passed rect is bigger then analog window
/////////////////////////////////////////////////////////////////////////////
ErrorCode Scaler::SetAnalogWin(const MRect &AWin)
{
AnalogWin_ = AWin;
return Success;
}
void Scaler::DumpSomeState()
{
UINT vDelay = regVDelay;
UINT vActive = regVActive;
UINT vScale = regVScale;
UINT hDelay = regHDelay;
UINT hActive = regHActive;
UINT hScale = regHScale;
MRect rect;
GetDigitalWin(rect);
DBGINFO(("vDelay = 0x%x\n", vDelay));
DBGINFO(("vActive = 0x%x\n", vActive));
DBGINFO(("vScale = 0x%x\n", vScale));
DBGINFO(("hDelay = 0x%x\n", hDelay));
DBGINFO(("hActive = 0x%x\n", hActive));
DBGINFO(("hScale = 0x%x\n", hScale));
DBGINFO(("top = 0x%x\n", rect.top));
DBGINFO(("left = 0x%x\n", rect.left));
DBGINFO(("right = 0x%x\n", rect.right));
DBGINFO(("bottom = 0x%x\n", rect.bottom));
}