📄 xdstorat.cpp
字号:
// XDSToRat.cpp : Implementation of CXDSToRat
#include "stdafx.h"
#include "CxTVRate.h"
#include "XDSToRat.h"
#include "XDSPacket.h"
#include "assert.h"
#include "cxTVRateDbg.h"
static
XDSPacket*
findPacket( std::list<XDSPacket> &xdsPackets, BYTE byte1, BYTE byte2 )
{
std::list<XDSPacket>::iterator i = xdsPackets.begin();
for( ; i != xdsPackets.end(); ++i )
if( i->ctrlCode() == byte1 && i->typeCode() == byte2 )
return &*i;
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CXDSToRat
CXDSToRat::CXDSToRat():
_p_receivingPkt( NULL )
{
InitializeCriticalSection( &_critSec );
}
CXDSToRat::~CXDSToRat()
{
DeleteCriticalSection( &_critSec );
}
STDMETHODIMP
CXDSToRat::Init()
{
EnterCriticalSection( &_critSec );
resetState();
LeaveCriticalSection( &_critSec );
DBP(( "XDStoRat::Init ------ called\n" ));
return S_OK;
}
STDMETHODIMP
CXDSToRat::ParseXDSBytePair( BYTE byte1,
BYTE byte2,
EnTvRat_System *p_system,
EnTvRat_GenericLevel *p_level,
LONG *p_attrib )
{
// If this byte pair does NOT complete a ratings(content advisory)
// packet we are supposed to return the following.
*p_system = TvRat_SystemDontKnow;
*p_level = TvRat_LevelDontKnow;
*p_attrib = BfAttrNone;
// Data is seven bit ASCII so make sure high order bit is cleared.
byte1 &= NBITS(7);
byte2 &= NBITS(7);
// If this byte pair is not: an XDS Control Code, a Caption/Text Control
// Code, or we do not have a receiving packet, just drop the data.
HRESULT hr = S_FALSE;
// Lock access to object data
EnterCriticalSection( &_critSec );
// Handle the XDS Start and Continue Control Codes. EIA/CEA-608-B Sec. 9.3
if( byte1 >= XDS_STRT_CUR && byte1 <= XDS_CONT_PRI )
{
if( byte1 & BIT(0) ) // Start Codes are odd.
{
// Check if this packet is already started and
// if so restart per EIA/CEA-608-B Sec. 8.6.8
if( _p_receivingPkt = findPacket( _xdsPackets, byte1, byte2 ) )
{
_p_receivingPkt->clearInfo();
}
else // Packet not started so create a new one.
{
_xdsPackets.push_front( XDSPacket( byte1, byte2 ) );
_p_receivingPkt = &*_xdsPackets.begin();
}
}
else // Continue Codes are even.
{
_p_receivingPkt = findPacket( _xdsPackets, byte1, byte2 );
}
hr = S_FALSE;
}
// Handle the XDS End Control Code. EIA/CEA-608-B Sec. 9.3
else if( byte1 == XDS_END_ALL )
{
hr = S_FALSE;
if( _p_receivingPkt )
{
// We need to get the receiving packet off the packet list because
// the decode functions may clear that list by calling Init().
XDSPacket pkt( *_p_receivingPkt );
_xdsPackets.remove( pkt );
_p_receivingPkt = NULL;
if( pkt.checkSum( byte2 ) )
hr = decodePacket( &pkt, p_system, p_level, p_attrib );
else
DBP(( "XDStoRat::Parse checkSum = %02x failed\n", byte2 ));
}
}
// Handle the Caption/Text Control Codes. EIA/CEA-608-B Sec. 8.6.2
else if( byte1 >= CAPTION_CTRL_MIN && byte1 <= CAPTION_CTRL_MAX )
{
_p_receivingPkt = NULL;
hr = S_FALSE;
}
// If we have a receiving packet add the byte pair to it.
else if( _p_receivingPkt )
{
_p_receivingPkt->addBytePair( byte1, byte2 );
hr = S_FALSE;
}
// Unlock access to object data
LeaveCriticalSection( &_critSec );
return hr;
}
HRESULT
CXDSToRat::decodePacket( XDSPacket *p_pkt,
EnTvRat_System *p_system,
EnTvRat_GenericLevel *p_level,
LONG *p_attrib )
{
assert( *p_system == TvRat_SystemDontKnow );
assert( *p_level == TvRat_LevelDontKnow );
assert( *p_attrib == BfAttrNone );
// Handle Program Identification number(PID) EIA/CEA-608-B Sec. 9.5.1.1
if( p_pkt->ctrlCode() == XDS_STRT_CUR && p_pkt->typeCode() == TY_PROG_ID )
{
return decodePID( p_pkt->info() );
}
// Handle Program Name EIA/CEA-608-B Sec. 9.5.1.3
else if( p_pkt->ctrlCode() == XDS_STRT_CUR &&
p_pkt->typeCode() == TY_PROG_NAME )
{
return decodeProgName( p_pkt->info() );
}
// Handle Content Advisory(Program Rating) EIA/CEA-608-B Sec. 9.5.1.5
else if( p_pkt->ctrlCode() == XDS_STRT_CUR &&
p_pkt->typeCode() == TY_CONTENT_ADVISORY )
{
return decodeContAdv( (p_pkt->info())[0], (p_pkt->info())[1],
true, // 2nd argument IS valid
p_system, p_level, p_attrib );
}
// Handle Composite Packet-1 to get the Program Name and Content Advisory
else if( p_pkt->ctrlCode() == XDS_STRT_CUR &&
p_pkt->typeCode() == TY_COMPOSITE_PKT1 )
{
if( p_pkt->info().size() < INFO_MIN_COMPOSITE_PKT1 )
return S_FALSE;
HRESULT nameHr = S_FALSE;
// If name is in packet check for new name.
if( p_pkt->info().size() > COMP_PKT1_PROG_NAME_OFST )
nameHr = decodeProgName( std::string( p_pkt->info(),
COMP_PKT1_PROG_NAME_OFST,
p_pkt->info().size() -
COMP_PKT1_PROG_NAME_OFST ) );
// If no Content Advisory is available NULL will be inserted.
if( (p_pkt->info())[COMP_PKT1_CONT_ADV_OFST] == 0 )
return nameHr;
HRESULT advHr = decodeContAdv( (p_pkt->info())[COMP_PKT1_CONT_ADV_OFST],
'U', // Unused argument
false, // 2nd argument is NOT valid
p_system, p_level, p_attrib );
return nameHr == S_OK || advHr == S_OK ? S_OK : S_FALSE;
}
// Handle Composite Packet-2 to get the PID EIA/CEA-608-B Sec. 9.5.1.11
else if( p_pkt->ctrlCode() == XDS_STRT_CUR &&
p_pkt->typeCode() == TY_COMPOSITE_PKT2 )
{
if( p_pkt->info().size() < INFO_MIN_COMPOSITE_PKT2 )
return S_FALSE;
// If no pid is available NULLs will be inserted Sec. 9.5.1.11
if( (p_pkt->info())[0] == 0 && (p_pkt->info())[1] == 0 &&
(p_pkt->info())[2] == 0 && (p_pkt->info())[3] == 0 )
return S_FALSE;
return decodePID( std::string( p_pkt->info(), 0, INFO_CNT_PROG_ID ) );
}
else
return S_FALSE;
}
HRESULT
CXDSToRat::decodePID( std::string newPID )
{
if( newPID.size() == INFO_CNT_PROG_ID )
{
// Only low order bits are used per Sec. 9.5.1.1
newPID[0] &= NBITS(6);
newPID[1] &= NBITS(5);
newPID[2] &= NBITS(5);
newPID[3] &= NBITS(5);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -