tsdemuxer.c

来自「Sun公司Dream项目」· C语言 代码 · 共 208 行

C
208
字号
/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the "License").  You may not use this file except
 * in compliance with the License.
 *
 * You can obtain a copy of the license at
 * http://www.opensource.org/licenses/cddl1.php
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * HEADER in each file and include the License file at
 * http://www.opensource.org/licenses/cddl1.php.  If 
 * applicable, add the following below this CDDL HEADER, 
 * with the fields enclosed by brackets "[]" replaced 
 * with your own identifying information: 
 * Portions Copyright [yyyy]
 * [name of copyright owner]
 */ 

/*
 * $(@)TsDemuxer.cc $Revision: 1.2 $ $Date: 2006/07/15 00:02:42 $
 * 
 * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
 */

#include "TsDemuxer.h"
#include "Filter.h"
#include "PsiFilter.h"
#include <iostream>
#include <stdexcept>
#include <cerrno>

namespace mpeg2ts {
    

class PatCallbackImpl: public PatCallback
{
public:
    PatCallbackImpl( TsDemuxer& demuxer ) : m_demuxer( demuxer ) {}
    
    virtual void operator()( Pat pat, unsigned int pid )
    {
        m_pat = pat;
        m_demuxer.setPatParsingDone(true);
    }
    
    Pat getPat() const 
    {
        return m_pat;
    }
    
private:
    TsDemuxer& m_demuxer;
    Pat        m_pat;
};

class PmtCallbackImpl: public PmtCallback
{
public:
    PmtCallbackImpl( TsDemuxer& demuxer ) : m_demuxer( demuxer ) {}
    
    virtual void operator()( Pmt pmt, unsigned int pid )
    {
        m_pmt = pmt;
        m_demuxer.setPmtParsingDone(true);
    }
    
    Pmt getPmt() const
    {
        return m_pmt;
    }
    
private:
    TsDemuxer& m_demuxer;
    Pmt        m_pmt;
};

TsDemuxer::TsDemuxer( std::string filename, Filter::Logging log )
    : m_patParsingDone( false ), m_tsFilter(log)
{
    std::fstream *infile = new std::fstream( filename.c_str(), 
                                             std::ios::in|std::ios::binary );
                                             
    if( ! *infile ) {
        std::cout << "TsDemuxer::TsDemuxer(): Error opening " << filename
                  << ": " << std::strerror(errno) << '\n';
        throw std::runtime_error( "FileOpenError" );   
    }
    
    m_file = FstreamPtr( infile );
    
}

static void feedData( std::fstream& strm, TsFilter& tsfilter )
{
    char tspkt[188];
    strm.read( tspkt, sizeof(tspkt) );
    int nread = strm.gcount();
    
    if( nread != sizeof(tspkt)  ) {
        if( strm.eof() ) {
            std::cout << "TsDemuxer feedData: fstream::read() End of File" << '\n';
            return;
        }
        else
            std::cout << "fstream::read(): Error: " << std::strerror(errno) << '\n';
        throw std::runtime_error( "Insufficient Data" );
    }
    
    if( !strm ) {
        std::cout << "ERROR: fstream::read() failed: " << std::strerror(errno) << '\n';
        throw std::runtime_error( "Bad Input Stream" );
    }
    
    tsfilter.process( m2t::Buffer( (unsigned char *)tspkt, nread ) );
}

std::pair<Pat, PmtList> TsDemuxer::getPatProgramList()
{
    m_numPmtsParsed = 0;
    
    PatCallbackImpl *patcb = new PatCallbackImpl( *this );
    boost::shared_ptr<PatFilter> patFilter( new PatFilter );
    m_tsFilter.setFilter( m2t::TsFilter::PatPid, patFilter );
    patFilter->setCallback( patcb );
    
    // PAT Callback code will set the m_patParsingDone flag after parsing PAT.
    while( !m_patParsingDone && *m_file  )
        feedData( *m_file, m_tsFilter );

    if( ! *m_file ) 
        throw std::runtime_error("Insufficient Data");
    
    m_patParsingDone = false;
    
    Pat pat = patcb->getPat();
    std::vector<PmtCallbackImpl *> pmtCbs;
    
    for( PatEntryList::iterator it=pat.entries.begin(); it!=pat.entries.end(); ++it ) 
    {
        std::cout << "ProgramNumber: " << (*it).programNumber.to_ulong()
            << "\tPID: " << (*it).programMapPid.to_ulong() << '\n';
            
        boost::shared_ptr<PmtFilter> pmtFilter( new PmtFilter );
        PmtCallbackImpl *pmtcb = new PmtCallbackImpl( *this );
        pmtFilter->setCallback( pmtcb );
        
        pmtCbs.push_back( pmtcb );
        
        m_tsFilter.setFilter( (*it).programMapPid.to_ulong(), pmtFilter );
    }
    
    m_numPmts = pat.entries.size();
        
    while( m_numPmtsParsed != m_numPmts && *m_file ) 
        feedData( *m_file, m_tsFilter );
    
    if( ! *m_file )
        throw std::runtime_error("Insufficient Data");
    
    m_numPmtsParsed = 0;
    
    PmtList pmts;
    
    for(std::vector<PmtCallbackImpl *>::iterator it = pmtCbs.begin();
            it!=pmtCbs.end(); ++it )
    {
        pmts.push_back( (*it)->getPmt() );
    }
   
    return std::make_pair(pat, pmts);
}

PmtList TsDemuxer::getProgramList()
{
    std::pair<Pat, PmtList> patPmt = getPatProgramList();
    return patPmt.second;
}
    
Filter *TsDemuxer::selectStream( unsigned long pid, FilterPtr streamProcessor )
{
    m_tsFilter.setFilter( pid, streamProcessor );
    return NULL;
}

int TsDemuxer::processAllData()
{
    while( *m_file ) {
        feedData( *m_file, m_tsFilter );
    }
    return 0;
}

void TsDemuxer::setPatParsingDone(bool value)
{
    m_patParsingDone = value;
}

void TsDemuxer::setPmtParsingDone(bool value)
{
    if( value==true )
        m_numPmtsParsed++;
}

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?