ecmgenerator.c
来自「Sun公司Dream项目」· C语言 代码 · 共 518 行 · 第 1/2 页
C
518 行
assert( size <= sizeof(key));
generate_key(key, size);
return std::string((const char *)key, size);
}
/******************************************************************************/
void EcmGenerator::operator()(m2t::Pmt pmt, unsigned int pmtPid)
{
unsigned pcrPid = pmt.pcrPid.to_ulong();
m_pCas->pid[pcrPid].b_seen = true;
m_pCas->pid[pcrPid].pn = pmt.programNumber.to_ulong();
assert( pmt.descriptors.size()==0 && "No CA Descriptors expected" );
for(m2t::PmtEntryList::iterator it=pmt.entries.begin(); it!=pmt.entries.end(); ++it)
{
unsigned elementaryPid = (*it).elementaryPid.to_ulong();
m_pCas->pid[elementaryPid].b_seen = true;
m_pCas->pid[elementaryPid].pn = pmt.programNumber.to_ulong();
}
/* look up the keys. do we need CA injection for this PMT ? */
TsCaDescriptorList tsCaDescriptorList;
for( EncryptionKeyList::iterator it=m_pCas->keys.begin();
it != m_pCas->keys.end(); ++it )
{
EncryptionKeyPtr pkeys = *it;
int keyCount = 0;
if( pkeys->pn==pmt.programNumber.to_ulong() || pkeys->pn==FOR_ANY_PROGRAM )
{
keyCount++;
if( pkeys->ecm_pid == 0 )
pkeys->ecm_pid = getFreePid( m_pCas, pmt.programNumber.to_ulong() );
TsCaDescriptorPtr caDesc( new ts_ca_descriptor_s( pkeys->e_type,
m_pCas->i_ca_system_id,
pkeys->ecm_pid,
NULL, 0 /*no private data*/) );
caDesc->p_key = pkeys.get();//FIXME: Make CADESC accept smart pointer
tsCaDescriptorList.push_back( caDesc );
}
}
assert( m_pCas->pid[pmtPid].b_seen == true );
assert( m_pCas->pid[pmtPid].pn == pmt.programNumber.to_ulong() );
assert( m_pCas->pid[pmtPid].b_pmt_pid == true );
TsBytes pmtTs = injectCaDescriptorToPmt( m_pCas, pmt, pmtPid, tsCaDescriptorList );
if( m_outfilter )
m_outfilter->process( m2t::Buffer(pmtTs.data,
sizeof(pmtTs.data), pmtTs.data, 0,
m2t::Buffer::UNIT_START, pmtPid ) );
if( m_pCas->b_outputECMafterPMT )
{
for(EncryptionKeyList::iterator it=m_pCas->keys.begin();
it != m_pCas->keys.end(); ++it )
{
EncryptionKeyPtr pkey = *it;
if( pkey->pn==pmt.programNumber.to_ulong() || pkey->pn==FOR_ANY_PROGRAM ) {
m_ecm = m_debugKeyType==GenerateNewKey
? Ecm( KeyGenerator::generateKey(), KeyGenerator::generateKey())
: Ecm( std::string("2222222222222222"),
std::string("0123456789012345"));
PsiBytes caSection = generateCaMessageSection( m_ecm, m_emm );
TsBytes caInTs = tsPacketizeCaMessage( m_pCas, pkey->ecm_pid,
caSection );
long long outpos=-1;
if( m_outfilter )
m_outfilter->process( m2t::Buffer((unsigned char *)caInTs.data,
sizeof(caInTs.data), caInTs.data,
0, m2t::Buffer::UNIT_START,
pkey->ecm_pid), outpos );
if( m_ecmOut ) {
unsigned char ecmBytes[1024];
m2t::OutputBitBuffer outb( ecmBytes, sizeof(ecmBytes) );
outb << m_ecm;
assert( outb.dataAvailable().first == m_ecm.sizeInBytes() );
m_ecmOut->process( m2t::Buffer( ecmBytes, m_ecm.sizeInBytes(),
ecmBytes, outpos, m2t::Buffer::UNIT_START,
pkey->ecm_pid ) );
}
}
}
}
return;
}
const Ecm& EcmGenerator::getCurrentEcm() const
{
return m_ecm;
}
static unsigned int getFreePid( ca_sys_t *pcas, unsigned long programNumber )
{
for(int i=0x10; i<0x01FFE; ++i) {
if( pcas->pid[i].b_seen == false ) {
pcas->pid[i].b_seen = true;
pcas->pid[i].pn = programNumber;
return i;
}
}
throw std::runtime_error("getFreePid(): No Free Pid found");
}
/*
----------------------------------------------------------------------
getStreamType: determine the stream type
ARGUMENTS:
i_stream_type: stream type value in the PMT es section
RETURN:
stream type
----------------------------------------------------------------------
*/
static encrypt_type getStreamType(int i_stream_type )
{
encrypt_type retType;
switch( i_stream_type )
{
case 0x01: /* MPEG-1 video */
case 0x02: /* MPEG-2 video */
case 0x80: /* MPEG-2 MOTO video */
case 0x10: /* MPEG4 (video) */
case 0x1B: /* H264 */
retType = ENCRYPT_VIDEO_ONLY;
break;
case 0x03: /* MPEG-1 audio */
case 0x04: /* MPEG-2 audio */
case 0x11: /* MPEG4 (audio) */
case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS transport syntax */
case 0x81: /* A52 (audio) */
case 0x83: /* LPCM (audio) */
case 0x84: /* SDDS (audio) */
case 0x85: /* DTS (audio) */
case 0x94: /* SDDS (audio) */
retType = ENCRYPT_AUDIO_ONLY;
break;
default:
retType = ENCRYPT_UNKNOWN;
break;
}
return retType;
}
TsBytes injectCaDescriptorToPmt( ca_sys_t *pcas, m2t::Pmt& pmt, unsigned int pmtPid,
TsCaDescriptorList& caList )
{
/* Add program level CA Descriptors */
for( TsCaDescriptorList::iterator it = caList.begin(); it != caList.end(); ++it )
{
if( (*it)->stream_type == ANY_STREAM_TYPE ) {
pmt.descriptors.push_back((*it)->desc);
}
}
/* Add Elementary stream level CA descriptors */
for(m2t::PmtEntryList::iterator it=pmt.entries.begin(); it!=pmt.entries.end(); ++it)
{
for( TsCaDescriptorList::iterator itdesc = caList.begin(); itdesc != caList.end(); ++itdesc )
{
if( getStreamType( (*it).streamType.to_ulong() ) == (*itdesc)->stream_type ) { (*it).descriptors.push_back( (*itdesc)->desc );
}
}
}
// Convert PMT to bytes
PsiBytes psibytes;
m2t::OutputBitBuffer outb( psibytes.data, sizeof(psibytes.data) );
assert( pmt.sizeInBytes() <= sizeof(psibytes.data) );
outb << pmt;
psibytes.length = pmt.sizeInBytes();
pcas->pid[pmtPid].continuity_counter++;
TsBytes tspkt = createTransportPacketForPsi( pmtPid,
pcas->pid[pmtPid].continuity_counter,
psibytes );
return tspkt;
}
PsiBytes generateCaMessageSection(const dream::cas::Ecm& ecm, const dream::cas::Emm& emm)
{
PsiBytes ecmSectionBytes;
unsigned char ecmBytes[1024];
m2t::OutputBitBuffer ecmout( ecmBytes, sizeof(ecmBytes) );
ecmout << ecm;
assert( ecmout.dataAvailable().first == ecm.sizeInBytes() );
int encryptedSize = encryptBufferData( ecmBytes, ecm.sizeInBytes(),
ecmBytes, sizeof(ecmBytes),
(unsigned char *)emm.entitlementTokenData.data(),
emm.entitlementTokenLength.to_ulong(),
(unsigned char *)emm.seedData.data(),
emm.seedLength.to_ulong(),
AES_MODE(emm.cryptoMode.to_ulong()) );
dream::cas::EcmSection ecmSection;
ecmSection.sectionLength = encryptedSize;
ecmSection.encryptedEcms.push_back( std::string((char *)ecmBytes, encryptedSize) );
m2t::OutputBitBuffer outb( ecmSectionBytes.data, sizeof(ecmSectionBytes.data) );
outb << ecmSection;
assert( outb.dataAvailable().second == 0 );
ecmSectionBytes.length = outb.dataAvailable().first;
return ecmSectionBytes;
}
TsBytes tsPacketizeCaMessage( ca_sys_t *pcas, unsigned int ecmPid, PsiBytes& caBytes )
{
pcas->pid[ecmPid].continuity_counter++;
TsBytes outTs = createTransportPacketForPsi( ecmPid,
pcas->pid[ecmPid].continuity_counter,
caBytes );
return outTs;
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?