📄 tsmux.cpp
字号:
/******************************************************************************** tsmux.cpp: TS multiplexer*-------------------------------------------------------------------------------* (c)1999-2002 VideoLAN* $Id: tsmux.cpp,v 1.5 2002/10/07 15:01:22 sam Exp $** Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**-------------------------------------------------------------------------------********************************************************************************///------------------------------------------------------------------------------// Preamble//------------------------------------------------------------------------------#include "../core/defs.h"#include "../core/core.h"#if defined(HAVE_INTTYPES_H)# include <inttypes.h>#elif defined(HAVE_STDINT_H)# include <stdint.h>#endif#ifdef HAVE_DVBPSI_DVBPSI_H# include <dvbpsi/dvbpsi.h># include <dvbpsi/descriptor.h># include <dvbpsi/pat.h># include <dvbpsi/pmt.h>#else# include "src/dvbpsi.h"# include "src/descriptor.h"# include "src/tables/pat.h"# include "src/tables/pmt.h"#endif#include "mpeg.h"#include "ts.h"#include "../server/buffer.h"#include "tsdemux.h"#include "dvbpsi.h"#include "tsmux.h"//******************************************************************************// C_TsMuxPmtDecoder class//******************************************************************************////******************************************************************************//------------------------------------------------------------------------------// Constructor//------------------------------------------------------------------------------C_TsMuxPmtDecoder::C_TsMuxPmtDecoder(C_NetList *pTsProvider, C_TsMux *pMux, u16 iProgramNumber) : C_DvbPsiPmtDecoder(iProgramNumber, pTsProvider, this){ ASSERT(pMux); m_pMux = pMux;}//------------------------------------------------------------------------------// Destructor//------------------------------------------------------------------------------C_TsMuxPmtDecoder::~C_TsMuxPmtDecoder(){}//------------------------------------------------------------------------------// PID unselection//------------------------------------------------------------------------------void C_TsMuxPmtDecoder::Detach(){ m_pMux->m_pDemux->Lock(); if(m_pCurrentPmt) { dvbpsi_pmt_t *pLLPmt = m_pCurrentPmt->GetLowLevelPmt(); m_pMux->m_pDemux->UnselectPid(m_pMux, pLLPmt->i_pcr_pid); dvbpsi_pmt_es_t* pEs = pLLPmt->p_first_es; while(pEs) { m_pMux->m_pDemux->UnselectPid(m_pMux, pEs->i_pid); printf("--- %x\n", pEs->i_pid); pEs = pEs->p_next; } } m_pMux->m_pDemux->UnLock();}//------------------------------------------------------------------------------// New PMT event//------------------------------------------------------------------------------void C_TsMuxPmtDecoder::OnDvbPsiPmtEvent(int iEvent){ if(iEvent == DVBPSI_EVENT_CURRENT) { C_DvbPsiPmt DiffPmtSub(0, 0, false, 0); C_DvbPsiPmt DiffPmtAdd(0, 0, false, 0); if(m_pPreviousPmt) { DiffPmtSub = *m_pPreviousPmt - *m_pCurrentPmt; DiffPmtAdd = *m_pCurrentPmt - *m_pPreviousPmt; } else { DiffPmtAdd = *m_pCurrentPmt; } dvbpsi_pmt_t *pLLPmt = DiffPmtSub.GetLowLevelPmt(); if(pLLPmt->i_pcr_pid) { dvbpsi_pmt_es_t* pEs = pLLPmt->p_first_es; while(pEs) { m_pMux->m_pDemux->UnselectPid(m_pMux, pEs->i_pid); printf("--- %x\n", pEs->i_pid); pEs = pEs->p_next; } } pLLPmt = DiffPmtAdd.GetLowLevelPmt(); dvbpsi_pmt_es_t* pEs = pLLPmt->p_first_es; while(pEs) { m_pMux->m_pDemux->SelectPid(m_pMux, pEs->i_pid, pEs->i_type); printf("+++ %x\n", pEs->i_pid); pEs = pEs->p_next; } m_pMux->m_pDemux->SelectPid(m_pMux, pLLPmt->i_pcr_pid, TS_TYPE_NULL); }}//******************************************************************************// C_TsMux class//******************************************************************************////******************************************************************************//------------------------------------------------------------------------------// Constructor//------------------------------------------------------------------------------C_TsMux::C_TsMux(C_NetList *pTsProvider, C_TsDemux *pDemux, I_TsPacketHandler *pHandler) : m_cPat(1, 0, true){ ASSERT(pTsProvider); ASSERT(pDemux); ASSERT(pHandler); m_pTsProvider = pTsProvider; m_pDemux = pDemux; m_pHandler = pHandler; m_bSendPat = true;}//------------------------------------------------------------------------------// Destructor//------------------------------------------------------------------------------C_TsMux::~C_TsMux(){}//------------------------------------------------------------------------------// Mux initialilzation//------------------------------------------------------------------------------void C_TsMux::Attach(){ // Lock the demux because we're running in another thread m_pDemux->Lock(); m_pDemux->SelectPid(this, 0x0000, TS_TYPE_NULL); m_pDemux->UnLock();}//------------------------------------------------------------------------------// Reset the multiplexer//------------------------------------------------------------------------------void C_TsMux::Detach(){ // Lock the demux because we're running in another thread m_pDemux->Lock(); C_HashTableIterator<u16, C_TsMuxPmtDecoder> cIterator = m_cPmtDecoders.CreateIterator(); while(cIterator.HasNext()) { C_HashTableNode<u16, C_TsMuxPmtDecoder> *pNode = cIterator.GetNext(); ASSERT(pNode); // Unlock the demux to allow DetachProgram to relock it. m_pDemux->UnLock(); DetachProgram(pNode->GetKey()); m_pDemux->Lock(); cIterator.Reset(); } m_pDemux->UnselectPid(this, 0x0000); m_pDemux->UnLock();}//------------------------------------------------------------------------------// Program selection//------------------------------------------------------------------------------void C_TsMux::AttachProgram(u16 iProgramNumber, u16 iPmtPid){ // Lock the demux because we're running in another thread m_pDemux->Lock(); ASSERT(!m_cPmtDecoders.Get(iPmtPid)); C_TsMuxPmtDecoder *pDecoder = new C_TsMuxPmtDecoder(m_pTsProvider, this, iProgramNumber); ASSERT(pDecoder); try { pDecoder->Attach(); m_cPmtDecoders.Add(iPmtPid, pDecoder); m_pDemux->SelectPid(this, iPmtPid, TS_TYPE_NULL); dvbpsi_pat_t *pLLPat = m_cPat.GetLowLevelPat(); pLLPat->i_version = (pLLPat->i_version + 1) & 0x1f; dvbpsi_PATAddProgram(pLLPat, iProgramNumber, iPmtPid); m_bSendPat = true; } catch(E_Exception e) { delete pDecoder; m_pDemux->UnLock(); throw e; } m_pDemux->UnLock();}//------------------------------------------------------------------------------// Program unselection//------------------------------------------------------------------------------void C_TsMux::DetachProgram(u16 iPmtPid){ // Lock the demux because we're running in another thread m_pDemux->Lock(); C_TsMuxPmtDecoder *pDecoder = m_cPmtDecoders.Remove(iPmtPid); ASSERT(pDecoder); // Unlock the demux to allow the PMT decoder to relock it. m_pDemux->UnLock(); pDecoder->Detach(); m_pDemux->Lock(); m_pDemux->UnselectPid(this, iPmtPid); dvbpsi_pat_t *pLLPat = m_cPat.GetLowLevelPat(); pLLPat->i_version = (pLLPat->i_version + 1) & 0x1f; dvbpsi_pat_program_t *pProgram = pLLPat->p_first_program; if(pProgram) { if(pProgram->i_pid == iPmtPid) { pLLPat->p_first_program = NULL; free(pProgram); } else { dvbpsi_pat_program_t *pProgram2 = pProgram->p_next; while((pProgram2) && (pProgram2->i_pid != iPmtPid)) { pProgram = pProgram2; pProgram2 = pProgram2->p_next; } if(pProgram2) { pProgram->p_next = pProgram2->p_next; free(pProgram2); } } } m_bSendPat = true; delete pDecoder; m_pDemux->UnLock();}//------------------------------------------------------------------------------// Input of the multiplexer//------------------------------------------------------------------------------void C_TsMux::HandlePacket(C_TsPacket* pPacket){ u16 iPid = pPacket->GetPid(); if(iPid == 0x0000) { m_bSendPat = true; m_pTsProvider->ReleasePacket(pPacket); } else { if(m_bSendPat) { m_cPat.Generate(); m_cPat.TsReset(); while(m_cPat.TsHasNext()) { C_TsPacket *pTsPat = m_pTsProvider->GetPacket(); ASSERT(pTsPat); m_cPat.TsWrite(pTsPat); m_pHandler->HandlePacket(pTsPat); } m_bSendPat = false; } C_TsMuxPmtDecoder *pDecoder = m_cPmtDecoders.Get(iPid); if(pDecoder) { pPacket->Ref(); pDecoder->HandlePacket(pPacket); } m_pHandler->HandlePacket(pPacket); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -