📄 ts.cpp
字号:
/******************************************************************************** ts.cpp: TS packet manipulation*-------------------------------------------------------------------------------* (c)1999-2001 VideoLAN* $Id: ts.cpp,v 1.2 2002/03/17 23:20:22 bozo Exp $** Authors: Benoit Steiner <benny@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 "config.h"#include "../core/core.h"#include "mpeg.h"#include "ts.h"//******************************************************************************// C_TsPacket class//******************************************************************************////******************************************************************************//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// Give direct access to the raw buffer//------------------------------------------------------------------------------C_TsPacket::operator byte* (){ return bData;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// Mark the packet as being invalid//------------------------------------------------------------------------------void C_TsPacket::IncrementCounter(){ u8 iByte = bData[3]; bData[3] = ((iByte + 1) & 0x0F) | (iByte & 0xF0);}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// Mark the packet as being invalid//------------------------------------------------------------------------------void C_TsPacket::SetErrorFlag(bool bError/* = true*/){ if(bError) bData[1] &= 0xFF; else bData[1] &= 0x7F;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// Set the discontinuity flag. This is only possible if the packet carries an// adaption field// Return false if the flag could not be set//------------------------------------------------------------------------------bool C_TsPacket::SetDiscontinuityFlag(bool bDiscontinuity/* = true*/){ bool bDone = true; // The job has to be done only if the flag must be set to true if(bDiscontinuity) { // Check that the adaptation_field_control is set and that the // adaptation_field_length is not 0 if((bData[3] & 0x20) && bData[4]) { // Set the discontinuity indicator bData[5] |= 0x80; } } else { // The flag can't be set bDone = false; } return bDone;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// Get the PID//------------------------------------------------------------------------------u16 C_TsPacket::GetPid() const{ return ((u16)(bData[1] & 0x1f) << 8) + bData[2];}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// Look for a PCR field in the TS header//------------------------------------------------------------------------------bool C_TsPacket::HasPCR() const{ // Return true only if adaptation_field_control is set, // adaptation_field_length is not 0 and PCR_flag is set return ((bData[3] & 0x20) && bData[4] && (bData[5] & 0x10));}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------////------------------------------------------------------------------------------bool C_TsPacket::IsDiscontinuity() const{ // Return true only if adaptation_field_control is set, // adaptation_field_length is not 0 and discontinuity_flag is set return ((bData[3] & 0x20) && bData[4] && (bData[5] & 0x80));}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// Extracts and converts the PCR to return a date in microseconds//------------------------------------------------------------------------------s64 C_TsPacket::GetPCRTime() const{ ASSERT(HasPCR()); // Make sure that the packet carries a PCR#ifdef SOLARIS // We need to align the data to avoid a bus error s64 i = *((s64*)(bData+4)); i = i >> 16; i = U32_AT(i); return ((( i << 1) | (bData[10] >> 7)) * 300) / 27;#else return ((( ((s64)U32_AT(bData[6])) << 1) | (bData[10] >> 7)) * 300) / 27;#endif}//------------------------------------------------------------------------------// BuildHeader: Build a TS header and return its size//------------------------------------------------------------------------------// Beware: only the 13 first bits of the iPid field are taken into account, and// only the 4 first bits of the iCounter are used// No adaption field can yet be put in the header// The method returns the length of the header//------------------------------------------------------------------------------u8 C_TsPacket::BuildHeader(u16 iPid, bool bUnitStart, u8 iCounter){ // For a PID is 13 bytes max ASSERT((iPid & 0xE000) == 0); // Sync byte bData[0] = 0x47; // Set PID value and both error indicator and priority to 0 SET_U16_TO(bData[1], iPid & 0x1FFF); // Payload unit start bData[1] |= bUnitStart << 6; // Continuity counter and no scrambling bData[3] = iCounter & 0x0F; // Adaption field control: always payload and never adaption field bData[3] |= 0x10; return 4;}//------------------------------------------------------------------------------// BuildAdaptionField: Build an adaption field for TS header and return its size//------------------------------------------------------------------------------// Append a PCR base to the adaption field. Overwrite all data that can follow// the header, so this method is to use before writing the actual payload//------------------------------------------------------------------------------u8 C_TsPacket::BuildAdaptionField(u64 iPCR){ // Adaption field control: adaption field is present bData[3] |= 0x20; // Adaption field length bData[4] = 1+6; // PCR_base is the only extension present in the adaption field bData[5] = 0x10; // PCR_base value SET_U32_TO(bData[6], (iPCR >> 1) & 0xFFFFFFFF); bData[10] = (iPCR & 0x1); return 4+2+6;}//------------------------------------------------------------------------------// AddStuffingBytes: Add stuff to complete the TS packet//------------------------------------------------------------------------------// Modify the TS header so that the necessary stuffing bytes are added to// complete the payload// Overwrite all data that can follow the header and the adaption field, so// this method is to use before writing the actual payload in the packet//------------------------------------------------------------------------------u8 C_TsPacket::AddStuffingBytes(u8 iPayloadLen){ // Check that the given payload length can fit in the packet and that it // is not big enough to fill it completely ASSERT(iPayloadLen < TS_PACKET_LEN - 4 - ((bData[3]&0x20)?bData[4]:0)); if(bData[3] & 0x20) { // There is an adaption field, we just have to extend it ASSERT(bData[4] > 0); // (Empty adaption fields are for stuffing only) ASSERT(TS_PACKET_LEN - 4 - 1 - bData[4] - iPayloadLen > 0); u8 iStuffStart = 4+1+bData[4]; bData[4] += TS_PACKET_LEN - iStuffStart - iPayloadLen; for(u8 i = 0; i < bData[4]; i++) bData[iStuffStart+i] = 0xFF; } else { // We must create the adaption field bData[3] |= 0x20; ASSERT(TS_PACKET_LEN - 4 - 1 - iPayloadLen >= 0); bData[4] = TS_PACKET_LEN - 4 - 1 - iPayloadLen; if(bData[4] > 0) { // We won't put any extension in the header bData[5] = 0; // Now write the stuffing bytes for(u8 i = 0; i < bData[4]; i++) bData[6+i] = 0xFF; } } // Check that we didn't made any error ASSERT(4+1+bData[4] + iPayloadLen == TS_PACKET_LEN); return TS_PACKET_LEN - iPayloadLen;}//******************************************************************************// C_PsiSection class//******************************************************************************// In the MPEG2 system norm, a section can be split into several TS packets, but// as this is really unuseful, our implementation don't allow sections biggest// than the size of the available payload of a TS packet.//******************************************************************************//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_PsiSection::C_PsiSection(){ // Init the CRC encoder BuildCrc32Table(); ZERO(m_iPsiStart);}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------/*C_PsiSection::~C_PsiSection(){}*///------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------u8 C_PsiSection::BuildHeader(u16 iPid, u8 iCounter, u8 iTableId, u16 iPsiId, u8 iVersion, bool bCurrentNext, u8 iCurrentSection, u8 iLastSection){ // For a PID is 13 bits max ASSERT((iPid & 0xE000) == 0); // For the version is 5 bits max ASSERT((iVersion & 0xE0) == 0); // First build the TS header: the unit_start indicator will be set to 1 // indicating that a PSI section begins in the packet m_iPsiStart = C_TsPacket::BuildHeader(iPid, true, iCounter);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -