📄 decoder.cpp
字号:
//==========================================================================;
//
// Decoder - Main decoder implementation
//
// $Date: 21 Aug 1998 21:46:26 $
// $Revision: 1.1 $
// $Author: Tashjian $
//
// $Copyright: (c) 1997 - 1998 ATI Technologies Inc. All Rights Reserved. $
//
//==========================================================================;
#include "mytypes.h"
#include "Scaler.h"
#include "decoder.h"
#include "dcdrvals.h"
#include "capmain.h"
#define CON_vs_BRI // HW does contrast incorrectly, try to adjust in SW
//===========================================================================
// Bt848 Decoder Class Implementation
//===========================================================================
#define REGALIGNMENT 1
/////////////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////////////
Decoder::Decoder(PDEVICE_PARMS pDeviceParms) :
// init register min, max, default
m_regHue(HueMin, HueMax, HueDef),
m_regSaturationNTSC(SatMinNTSC, SatMaxNTSC, SatDefNTSC),
m_regSaturationSECAM(SatMinSECAM, SatMaxSECAM, SatDefSECAM),
m_regContrast(ConMin, ConMax, ConDef),
m_regBrightness(BrtMin, BrtMax, BrtDef),
m_param(ParamMin, ParamMax, ParamDef),
decRegSTATUS (((0x00 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldHLOC(decRegSTATUS, 6, 1, RW) ,
decFieldNUML(decRegSTATUS, 4, 1, RW) ,
decFieldCSEL(decRegSTATUS, 3, 1, RW) ,
decFieldSTATUS_RES(decRegSTATUS, 2, 1, RW) ,
decFieldLOF(decRegSTATUS, 1, 1, RW) ,
decFieldCOF(decRegSTATUS, 0, 1, RW) ,
decRegIFORM (((0x01 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldHACTIVE(decRegIFORM, 7, 1, RW) ,
decFieldMUXSEL(decRegIFORM, 5, 2, RW) ,
decFieldXTSEL(decRegIFORM, 3, 2, RW) ,
decFieldFORMAT(decRegIFORM, 0, 3, RW) ,
decRegTDEC (((0x02 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldDEC_FIELD(decRegTDEC, 7, 1, RW) ,
decFieldDEC_FIELDALIGN(decRegTDEC, 6, 1, RW) ,
decFieldDEC_RAT(decRegTDEC, 0, 6, RW) ,
decRegBRIGHT (((0x0A + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegMISCCONTROL (((0x0B + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldLNOTCH(decRegMISCCONTROL, 7, 1, RW) ,
decFieldCOMP(decRegMISCCONTROL, 6, 1, RW) ,
decFieldLDEC(decRegMISCCONTROL, 5, 1, RW) ,
decFieldMISCCONTROL_RES(decRegMISCCONTROL, 3, 1, RW) ,
decFieldCON_MSB(decRegMISCCONTROL, 2, 1, RW) ,
decFieldSAT_U_MSB(decRegMISCCONTROL, 1, 1, RW) ,
decFieldSAT_V_MSB(decRegMISCCONTROL, 0, 1, RW) ,
decRegCONTRAST_LO (((0x0C + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegSAT_U_LO (((0x0D + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegSAT_V_LO (((0x0E + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegHUE (((0x0F + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegSCLOOP (((0x10 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldCAGC(decRegSCLOOP, 6, 1, RW) ,
decFieldCKILL(decRegSCLOOP, 5, 1, RW) ,
decRegWC_UP(((0x11 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegOFORM (((0x12 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldVBI_FRAME(decRegOFORM, 4, 1, RW) ,
decFieldCODE(decRegOFORM, 3, 1, RW) ,
decFieldLEN(decRegOFORM, 2, 1, RW) ,
decRegVSCALE_HI (((0x13 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldYCOMB(decRegVSCALE_HI, 7, 1, RW) ,
decFieldCOMB(decRegVSCALE_HI, 6, 1, RW) ,
decFieldINT(decRegVSCALE_HI, 5, 1, RW) ,
decRegTEST (((0x15 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegVPOLE (((0x16 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldOUT_EN (decRegVPOLE, 7, 1, RW),
decFieldDVALID (decRegVPOLE, 6, 1, RW),
decFieldVACTIVE (decRegVPOLE, 5, 1, RW),
decFieldCBFLAG (decRegVPOLE, 4, 1, RW),
decFieldFIELD (decRegVPOLE, 3, 1, RW),
decFieldACTIVE (decRegVPOLE, 2, 1, RW),
decFieldHRESET (decRegVPOLE, 1, 1, RW),
decFieldVRESET (decRegVPOLE, 0, 1, RW),
decRegADELAY (((0x18 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegBDELAY (((0x19 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegADC (((0x1A + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldCLK_SLEEP(decRegADC, 3, 1, RW) ,
decFieldC_SLEEP(decRegADC, 1, 1, RW) ,
decFieldCRUSH(decRegADC, 0, 1, RW),
decRegVTC (((0x1B + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decFieldHSFMT(decRegVTC, 7, 1, RW) ,
decRegWC_DN(((0x1E + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
decRegSRESET (((0x1F + 0) * REGALIGNMENT) + 0, RW, pDeviceParms),
decRegODD_MISCCONTROL (((0x0B + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
decFieldODD_LNOTCH(decRegODD_MISCCONTROL, 7, 1, RW) ,
decFieldODD_COMP(decRegODD_MISCCONTROL, 6, 1, RW) ,
decFieldODD_LDEC(decRegODD_MISCCONTROL, 5, 1, RW) ,
decFieldODD_CBSENSE(decRegODD_MISCCONTROL, 4, 1, RW) ,
decFieldODD_MISCCONTROL_RES(decRegODD_MISCCONTROL, 3, 1, RW) ,
decFieldODD_CON_MSB(decRegODD_MISCCONTROL, 2, 1, RW) ,
decFieldODD_SAT_U_MSB(decRegODD_MISCCONTROL, 1, 1, RW) ,
decFieldODD_SAT_V_MSB(decRegODD_MISCCONTROL, 0, 1, RW) ,
decRegODD_SCLOOP (((0x10 + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
decFieldODD_CAGC(decRegODD_SCLOOP, 6, 1, RW) ,
decFieldODD_CKILL(decRegODD_SCLOOP, 5, 1, RW) ,
decFieldODD_HFILT(decRegODD_SCLOOP, 3, 2, RW) ,
decRegODD_VSCALE_HI (((0x13 + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
decFieldODD_YCOMB(decRegODD_VSCALE_HI, 7, 1, RW) ,
decFieldODD_COMB(decRegODD_VSCALE_HI, 6, 1, RW) ,
decFieldODD_INT(decRegODD_VSCALE_HI, 5, 1, RW) ,
decRegODD_VTC (((0x1B + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
decFieldODD_HSFMT(decRegODD_VTC, 7, 1, RW)
{
if(!(pDeviceParms->chipRev < 4))
{
// need to set this to 0x4F
decRegWC_UP = 0x4F;
// and this one to 0x7F to make sure CRUSH bit works for not plain vanila BT829
decRegWC_DN = 0x7F;
}
// HACTIVE should always be 0
decFieldHACTIVE = 0;
decFieldHSFMT = 0;
// The following lines were commented out in an attempt to
// have a picture which closely matches what an ordinary TV would
// show. However, it should be noted that Brooktree recommended to
// comment out only the 'SetLowColorAutoRemoval' line. Probably the
// best solution of all would be to somehow expose these options
// to the application.
// Instead of using default values, set some registers fields to optimum values
/*
SetLumaDecimation(TRUE);
SetChromaAGC(TRUE);
SetLowColorAutoRemoval(FALSE);
SetAdaptiveAGC(FALSE);
*/
// for contrast adjustment purpose
regBright = 0x00; // brightness register value before adjustment
regContrast = 0xD8; // contrast register value before adjustment
m_supportedVideoStandards = KS_AnalogVideo_NTSC_M |
KS_AnalogVideo_NTSC_M_J |
KS_AnalogVideo_PAL_B |
KS_AnalogVideo_PAL_D |
KS_AnalogVideo_PAL_G |
KS_AnalogVideo_PAL_H |
KS_AnalogVideo_PAL_I |
KS_AnalogVideo_PAL_M |
KS_AnalogVideo_PAL_N; //Paul: what BT 829 can support (from L829A_A functional Description)
if(!(pDeviceParms->chipRev < 4))
m_supportedVideoStandards |= KS_AnalogVideo_SECAM_B |
KS_AnalogVideo_SECAM_D |
KS_AnalogVideo_SECAM_G |
KS_AnalogVideo_SECAM_H |
KS_AnalogVideo_SECAM_K |
KS_AnalogVideo_SECAM_K1 |
KS_AnalogVideo_SECAM_L |
KS_AnalogVideo_SECAM_L1;
m_supportedVideoStandards &= pDeviceParms->ulVideoInStandardsSupportedByCrystal; //Paul: AND with whatever supported by the onboard crystal
// jaybo
// loop until we find a supported TV standard, and use that to init
UINT k;
for (k = 1; k; k += k) {
if (k & m_supportedVideoStandards) {
SetVideoDecoderStandard(k);
break;
}
}
// end jaybo
}
/////////////////////////////////////////////////////////////////////////////
// Destructor
/////////////////////////////////////////////////////////////////////////////
Decoder::~Decoder()
{
}
void Decoder::GetVideoDecoderCaps(PKSPROPERTY_VIDEODECODER_CAPS_S pS)
{
pS->StandardsSupported = m_supportedVideoStandards;
pS->Capabilities = KS_VIDEODECODER_FLAGS_CAN_DISABLE_OUTPUT |
KS_VIDEODECODER_FLAGS_CAN_INDICATE_LOCKED ;
// How long (ms) til locked indicator is valid.
// 31 line periods * 63.5uS per line.
pS->SettlingTime = 2;
// Not sure about this
// HSync per VSync
pS->HSyncPerVSync = 6;
}
void Decoder::GetVideoDecoderStatus(PKSPROPERTY_VIDEODECODER_STATUS_S pS)
{
pS->NumberOfLines = Is525LinesVideo() ? 525 : 625;
pS->SignalLocked = decFieldHLOC == 1;
}
DWORD Decoder::GetVideoDecoderStandard()
{
return m_videoStandard; //Paul
}
BOOL Decoder::SetVideoDecoderStandard(DWORD standard)
{
if (m_supportedVideoStandards & standard) //Paul: standard must be a supported standard
{
m_videoStandard = standard;
switch ( m_videoStandard )
{
case KS_AnalogVideo_NTSC_M:
Decoder::SetVideoFormat(VFormat_NTSC);
break;
case KS_AnalogVideo_NTSC_M_J:
Decoder::SetVideoFormat(VFormat_NTSC_J);
break;
case KS_AnalogVideo_PAL_B:
case KS_AnalogVideo_PAL_D:
case KS_AnalogVideo_PAL_G:
case KS_AnalogVideo_PAL_H:
case KS_AnalogVideo_PAL_I:
Decoder::SetVideoFormat(VFormat_PAL_BDGHI); // PAL_BDGHI covers most areas
break;
case KS_AnalogVideo_PAL_M:
Decoder::SetVideoFormat(VFormat_PAL_M);
break;
case KS_AnalogVideo_PAL_N:
Decoder::SetVideoFormat(VFormat_PAL_N_COMB);
break;
default: //Paul: SECAM
Decoder::SetVideoFormat(VFormat_SECAM);
}
return TRUE;
}
else
return FALSE;
}
//===== Device Status register ==============================================
/////////////////////////////////////////////////////////////////////////////
// Method: BOOL Decoder::Is525LinesVideo()
// Purpose: Check to see if we are dealing with 525 lines video signal
// Input: None
// Output: None
// Return: TRUE if 525 lines detected; else FALSE (assume 625 lines)
/////////////////////////////////////////////////////////////////////////////
BOOL Decoder::Is525LinesVideo()
{
return (BOOL) (decFieldNUML == 0); //525
}
/////////////////////////////////////////////////////////////////////////////
// Method: BOOL Decoder::IsCrystal0Selected()
// Purpose: Reflect whether XTAL0 or XTAL1 is selected
// Input: None
// Output: None
// Return: TRUE if XTAL0 selected; else FALSE (XTAL1 selected)
/////////////////////////////////////////////////////////////////////////////
BOOL Decoder::IsCrystal0Selected()
{
return (BOOL) (decFieldCSEL == 0);
}
/////////////////////////////////////////////////////////////////////////////
// Method: BOOL Decoder::IsLumaOverflow()
// Purpose: Indicates if luma ADC overflow
// Input: None
// Output: None
// Return: TRUE if luma ADC overflow; else FALSE
/////////////////////////////////////////////////////////////////////////////
BOOL Decoder::IsLumaOverflow()
{
return (BOOL) (decFieldLOF == 1);
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Decoder::ResetLumaOverflow()
// Purpose: Reset luma ADC overflow bit
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Decoder::ResetLumaOverflow()
{
decFieldLOF = 0; // write to it will reset the bit
}
/////////////////////////////////////////////////////////////////////////////
// Method: BOOL Decoder::IsChromaOverflow()
// Purpose: Indicates if chroma ADC overflow
// Input: None
// Output: None
// Return: TRUE if chroma ADC overflow; else FALSE
/////////////////////////////////////////////////////////////////////////////
BOOL Decoder::IsChromaOverflow()
{
return (BOOL) (decFieldCOF == 1);
}
/////////////////////////////////////////////////////////////////////////////
// Method: void Decoder::ResetChromaOverflow()
// Purpose: Reset chroma ADC overflow bit
// Input: None
// Output: None
// Return: None
/////////////////////////////////////////////////////////////////////////////
void Decoder::ResetChromaOverflow()
{
decFieldCOF = 0; // write to it will reset the bit
}
//===== Input Format register ===============================================
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -