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 + -
显示快捷键?