Convert to LibMist

This commit is contained in:
Erik Zandvliet 2012-07-14 13:36:34 +00:00 committed by Thulinma
parent dcd67784ed
commit 2ec7cc00c5
5 changed files with 0 additions and 691 deletions

View file

@ -1,23 +0,0 @@
noinst_LTLIBRARIES=libamf.la libauth.la libbase64.la libconfig.la libcrypto.la libdtsc.la libflv_tag.la libhttp_parser.la libjson.la libprocs.la librtmpchunks.la libsocket.la libtinythread.la libmp4.la libts_packet.la libnal_unit.la
libamf_la_SOURCES=amf.h amf.cpp
libauth_la_SOURCES=auth.h auth.cpp
libauth_la_LIBADD=-lssl -lcrypto
libbase64_la_SOURCES=base64.h base64.cpp
libconfig_la_SOURCES=config.h config.cpp
libcrypto_la_SOURCES=crypto.h crypto.cpp
libcrypto_la_LIBADD=-lssl -lcrypto
libdtsc_la_SOURCES=dtsc.h dtsc.cpp
libflv_tag_la_SOURCES=flv_tag.h flv_tag.cpp
libflv_tag_la_LIBADD=./libamf.la ./libsocket.la
libhttp_parser_la_SOURCES=http_parser.h http_parser.cpp
libjson_la_SOURCES=json.h json.cpp
libprocs_la_SOURCES=procs.h procs.cpp
librtmpchunks_la_SOURCES=rtmpchunks.h rtmpchunks.cpp
librtmpchunks_la_LIBADD=./libflv_tag.la -lssl -lcrypto
libsocket_la_SOURCES=socket.h socket.cpp
libtinythread_la_SOURCES=tinythread.h tinythread.cpp
libtinythread_la_LIBADD=-lpthread
libmp4_la_SOURCES=mp4.h mp4.cpp
libts_packet_la_SOURCES=ts_packet.h ts_packet.cpp
libts_packet_la_LIBADD=./libdtsc.la
libnal_unit_la_SOURCES=nal.h nal.cpp

View file

@ -1,71 +0,0 @@
#include "nal.h"
NAL_Unit::NAL_Unit( ) {
}
NAL_Unit::NAL_Unit( std::string & InputData ) {
ReadData( InputData );
}
bool NAL_Unit::ReadData( std::string & InputData ) {
std::string FullAnnexB;
FullAnnexB += (char)0x00;
FullAnnexB += (char)0x00;
FullAnnexB += (char)0x00;
FullAnnexB += (char)0x01;
std::string ShortAnnexB;
ShortAnnexB += (char)0x00;
ShortAnnexB += (char)0x00;
ShortAnnexB += (char)0x01;
// fprintf( stderr, "NAL_Unit::ReadData --- DataSize: %d\n", InputData.size() );
if( InputData.size() < 3 ) { return false; }
bool AnnexB = false;
if( InputData.substr(0,3) == ShortAnnexB ) { AnnexB = true; }
if( InputData.substr(0,4) == FullAnnexB ) { InputData.erase(0,1); AnnexB = true; }
if( AnnexB ) {
MyData = "";
InputData.erase(0,3);//Intro Bytes
bool FinalByteRead = false;
int Location = std::min( InputData.find( ShortAnnexB ), InputData.find( FullAnnexB ) );
MyData = InputData.substr(0,Location);
InputData.erase(0,Location);
} else {
if( InputData.size() < 4 ) { return false; }
int UnitLen = (InputData[0] << 24) + (InputData[1] << 16) + (InputData[2] << 8) + InputData[3];
if( InputData.size() < 4+UnitLen ) { return false; }
InputData.erase(0,4);//Remove Length
MyData = InputData.substr(0,UnitLen);
InputData.erase(0,UnitLen);//Remove this unit from the string
}
return true;
}
std::string NAL_Unit::AnnexB( bool LongIntro ) {
std::string Result;
if( MyData.size() ) {
if( LongIntro ) { Result += (char)0x00; }
Result += (char)0x00;
Result += (char)0x00;
Result += (char)0x01;//Annex B Lead-In
Result += MyData;
}
return Result;
}
std::string NAL_Unit::SizePrepended( ) {
std::string Result;
if( MyData.size() ) {
int DataSize = MyData.size();
Result += (char)( ( DataSize & 0xFF000000 ) >> 24 );
Result += (char)( ( DataSize & 0x00FF0000 ) >> 16 );
Result += (char)( ( DataSize & 0x0000FF00 ) >> 8 );
Result += (char)( DataSize & 0x000000FF );//Size Lead-In
Result += MyData;
}
return Result;
}
int NAL_Unit::Type( ) {
return ( MyData[0] & 0x1F );
}

View file

@ -1,14 +0,0 @@
#include <string>
#include <cstdio>
class NAL_Unit {
public:
NAL_Unit( );
NAL_Unit( std::string & InputData );
bool ReadData( std::string & InputData );
std::string AnnexB( bool LongIntro = false );
std::string SizePrepended( );
int Type( );
private:
std::string MyData;
};//NAL_Unit class

View file

@ -1,430 +0,0 @@
/// \file ts_packet.cpp
/// Holds all code for the TS namespace.
#include "ts_packet.h"
/// This constructor creates an empty TS::Packet, ready for use for either reading or writing.
/// All this constructor does is call TS::Packet::Clear().
TS::Packet::Packet() { Clear( ); }
/// This function fills a TS::Packet from provided Data.
/// It fills the content with the first 188 bytes of Data.
/// \param Data The data to be read into the packet.
/// \return true if it was possible to read in a full packet, false otherwise.
bool TS::Packet::FromString( std::string & Data ) {
if( Data.size() < 188 ) {
return false;
} else {
for( int i = 0; i < 188; i++ ) { Buffer[i] = Data[i]; }
Data.erase(0,188);
Free = 0;
}
return true;
}
/// The deconstructor deletes all space that may be occupied by a TS::Packet.
TS::Packet::~Packet() { }
/// Sets the PID of a single TS::Packet.
/// \param NewPID The new PID of the packet.
void TS::Packet::PID( int NewPID ) {
Buffer[1] = (Buffer[1] & 0xE0) + ((NewPID & 0x1F00) >> 8 );
Buffer[2] = (NewPID & 0x00FF);
Free = std::min( Free, 184 );
}
/// Gets the PID of a single TS::Packet.
/// \return The value of the PID.
int TS::Packet::PID() {
return (( Buffer[1] & 0x1F ) << 8 ) + Buffer[2];
}
/// Sets the Continuity Counter of a single TS::Packet.
/// \param NewContinuity The new Continuity Counter of the packet.
void TS::Packet::ContinuityCounter( int NewContinuity ) {
Buffer[3] = ( Buffer[3] & 0xF0 ) + ( NewContinuity & 0x0F );
Free = std::min( Free, 184 );
}
/// Gets the Continuity Counter of a single TS::Packet.
/// \return The value of the Continuity Counter.
int TS::Packet::ContinuityCounter() {
return ( Buffer[3] & 0x0F );
}
/// Gets the amount of bytes that are not written yet in a TS::Packet.
/// \return The amount of bytes that can still be written to this packet.
int TS::Packet::BytesFree( ) {
return Free;
}
/// Clears a TS::Packet.
void TS::Packet::Clear( ) {
Free = 184;
Buffer[0] = 0x47;
for( int i = 1; i < 188; i++ ) { Buffer[i] = 0x00; }
AdaptationField( 1 );
}
/// Sets the selection value for an adaptationfield of a TS::Packet.
/// \param NewSelector The new value of the selection bits.
/// - 1: No AdaptationField.
/// - 2: AdaptationField Only.
/// - 3: AdaptationField followed by Data.
void TS::Packet::AdaptationField( int NewSelector ) {
Buffer[3] = ( Buffer[3] & 0xCF ) + ((NewSelector & 0x03) << 4);
Buffer[4] = 0;
Free = std::min( Free, 184 );
}
/// Gets whether a TS::Packet contains an adaptationfield.
/// \return The existence of an adaptationfield.
/// - 0: No adaptationfield present.
/// - 1: Adaptationfield is present.
int TS::Packet::AdaptationField( ) {
return ((Buffer[3] & 0x30) >> 4 );
}
/// Sets the PCR (Program Clock Reference) of a TS::Packet.
/// \param NewVal The new PCR Value.
void TS::Packet::PCR( int64_t NewVal ) {
AdaptationField( 3 );
Buffer[4] = 7;
Buffer[5] = (Buffer[5] | 0x10 );
int64_t TmpVal = NewVal / 300;
fprintf( stderr, "\tSetting PCR_Base: %d\n", TmpVal );
Buffer[6] = (((TmpVal>>1)>>24) & 0xFF);
Buffer[7] = (((TmpVal>>1)>>16) & 0xFF);
Buffer[8] = (((TmpVal>>1)>>8) & 0xFF);
Buffer[9] = ((TmpVal>>1) & 0xFF);
int Remainder = NewVal % 300;
Buffer[10] = 0x7E + ((TmpVal & 0x01)<<7) + ((Remainder & 0x0100) >> 8 );
Buffer[11] = (Remainder & 0x00FF);
Free = std::min( Free, 176 );
};
/// Gets the PCR (Program Clock Reference) of a TS::Packet.
/// \return The value of the PCR.
int64_t TS::Packet::PCR( ) {
if( !AdaptationField() ) {
return -1;
}
if( !(Buffer[5] & 0x10 ) ) {
return -1;
}
int64_t Result = 0;
Result = (((((((Buffer[6] << 8) + Buffer[7]) << 8) + Buffer[8]) << 8) + Buffer[9]) << 1) + ( Buffer[10] & 0x80 );
Result = Result * 300;
Result += ((Buffer[10] & 0x01) << 8 + Buffer[11]);
return Result;
}
/// Gets the current length of the adaptationfield.
/// \return The length of the adaptationfield.
int TS::Packet::AdaptationFieldLen( ) {
if( !AdaptationField() ) {
return -1;
}
return (int)Buffer[4];
}
/// Prints a packet to stdout, for analyser purposes.
void TS::Packet::Print( ) {
std::cout << "TS Packet: " << (Buffer[0] == 0x47)
<< "\n\tNewUnit: " << UnitStart()
<< "\n\tPID: " << PID()
<< "\n\tContinuity Counter: " << ContinuityCounter()
<< "\n\tAdaption Field: " << AdaptationField() << "\n";
if( AdaptationField() ) {
std::cout << "\t\tAdaption Field Length: " << AdaptationFieldLen() << "\n";
if( AdaptationFieldLen() ) {
std::cout << "\t\tRandom Access: " << RandomAccess() << "\n";
}
if( PCR() != -1 ) {
std::cout << "\t\tPCR: " << PCR() << "( " << (double)PCR() / 27000000 << " s )\n";
}
}
}
/// Gets whether a new unit starts in this TS::Packet.
/// \return The start of a new unit.
int TS::Packet::UnitStart( ) {
return ( Buffer[1] & 0x40) >> 6;
}
/// Sets the start of a new unit in this TS::Packet.
/// \param NewVal The new value for the start of a unit.
void TS::Packet::UnitStart( int NewVal ) {
if( NewVal ) {
Buffer[1] = (Buffer[1] | 0x40);
} else {
Buffer[1] = (Buffer[1] & 0xBF);
}
}
/// Gets whether this TS::Packet can be accessed at random (indicates keyframe).
/// \return Whether or not this TS::Packet contains a keyframe.
int TS::Packet::RandomAccess( ) {
if( AdaptationField() < 2 ) {
return -1;
}
return ( Buffer[5] & 0x40) >> 6;
}
/// Sets whether this TS::Packet contains a keyframe
/// \param NewVal Whether or not this TS::Packet contains a keyframe.
void TS::Packet::RandomAccess( int NewVal ) {
if( AdaptationField() ) {
if( Buffer[4] == 0 ) {
Buffer[4] = 1;
}
if( NewVal ) {
Buffer[5] = (Buffer[5] | 0x40);
} else {
Buffer[5] = (Buffer[5] & 0xBF);
}
} else {
AdaptationField( 3 );
Buffer[4] = 1;
if( NewVal ) {
Buffer[5] = 0x40;
} else {
Buffer[5] = 0x00;
}
}
Free = std::min( Free, 182 );
}
/// Transforms the TS::Packet into a standard Program Association Table
void TS::Packet::DefaultPAT( ) {
static int MyCntr = 0;
std::copy( TS::PAT, TS::PAT + 188, Buffer );
ContinuityCounter( MyCntr );
Free = 0;
MyCntr = ( (MyCntr + 1) % 0x10);
}
/// Transforms the TS::Packet into a standard Program Mapping Table
void TS::Packet::DefaultPMT( ) {
static int MyCntr = 0;
std::copy( TS::PMT, TS::PMT + 188, Buffer );
ContinuityCounter( MyCntr );
Free = 0;
MyCntr = ( (MyCntr + 1) % 0x10);
}
/// Generates a string from the contents of the TS::Packet
/// \return A string representation of the packet.
std::string TS::Packet::ToString( ) {
std::string Result( Buffer, 188 );
std::cout.write( Buffer,188 );
return Result;
}
/// Generates a PES Lead-in for a video frame.
/// Starts at the first Free byte.
/// \param NewLen The length of this video frame.
void TS::Packet::PESVideoLeadIn( int NewLen ) {
static int PTS = 126000;
NewLen += 14;
int Offset = ( 188 - Free );
Buffer[Offset] = 0x00;//PacketStartCodePrefix
Buffer[Offset+1] = 0x00;//PacketStartCodePrefix (Cont)
Buffer[Offset+2] = 0x01;//PacketStartCodePrefix (Cont)
Buffer[Offset+3] = 0xe0;//StreamType Video
Buffer[Offset+4] = (NewLen & 0xFF00) >> 8;//PES PacketLength
Buffer[Offset+5] = (NewLen & 0x00FF);//PES PacketLength (Cont)
Buffer[Offset+6] = 0x80;//Reserved + Flags
Buffer[Offset+7] = 0x80;//PTSOnlyFlag + Flags
Buffer[Offset+8] = 0x05;//PESHeaderDataLength
Buffer[Offset+9] = 0x20 + ((PTS & 0x1C0000000) >> 29 ) + 1;//PTS
Buffer[Offset+10] = 0x00 + ((PTS & 0x03FC00000) >> 22 );//PTS (Cont)
Buffer[Offset+11] = 0x00 + ((PTS & 0x0003F8000) >> 14 ) + 1;//PTS (Cont)
Buffer[Offset+12] = 0x00 + ((PTS & 0x000007F80) >> 7 );//PTS (Cont)
Buffer[Offset+13] = 0x00 + ((PTS & 0x00000007F) << 1) + 1;//PTS (Cont)
//PesPacket-Wise Prepended Data
Buffer[Offset+14] = 0x00;//NALU StartCode
Buffer[Offset+15] = 0x00;//NALU StartCode (Cont)
Buffer[Offset+16] = 0x00;//NALU StartCode (Cont)
Buffer[Offset+17] = 0x01;//NALU StartCode (Cont)
Buffer[Offset+18] = 0x09;//NALU EndOfPacket (Einde Vorige Packet)
Buffer[Offset+19] = 0xF0;//NALU EndOfPacket (Cont)
Free = Free - 20;
PTS += 3003;
}
/// Generates a PES Lead-in for an audio frame.
/// Starts at the first Free byte.
/// \param NewLen The length of this audio frame.
/// \param PTS The timestamp of the audio frame.
void TS::Packet::PESAudioLeadIn( int NewLen, uint64_t PTS ) {
PTS = PTS * 90;
NewLen += 8;
int Offset = ( 188 - Free ) - 2;
Buffer[Offset] = 0x00;//PacketStartCodePrefix
Buffer[Offset+1] = 0x00;//PacketStartCodePrefix (Cont)
Buffer[Offset+2] = 0x01;//PacketStartCodePrefix (Cont)
Buffer[Offset+3] = 0xc0;//StreamType Video
Buffer[Offset+4] = (NewLen & 0xFF00) >> 8;//PES PacketLength
Buffer[Offset+5] = (NewLen & 0x00FF);//PES PacketLength (Cont)
Buffer[Offset+6] = 0x80;//Reserved + Flags
Buffer[Offset+7] = 0x80;//PTSOnlyFlag + Flags
Buffer[Offset+8] = 0x05;//PESHeaderDataLength
Buffer[Offset+9] = 0x20 + ((PTS & 0x1C0000000) >> 29 ) + 1;//PTS
Buffer[Offset+10] = 0x00 + ((PTS & 0x03FC00000) >> 22 );//PTS (Cont)
Buffer[Offset+11] = 0x00 + ((PTS & 0x0003F8000) >> 14 ) + 1;//PTS (Cont)
Buffer[Offset+12] = 0x00 + ((PTS & 0x000007F80) >> 7 );//PTS (Cont)
Buffer[Offset+13] = 0x00 + ((PTS & 0x00000007F) << 1) + 1;//PTS (Cont)
Free = Free - 12;
}
/// Fills the free bytes of the TS::Packet.
/// Stores as many bytes from NewVal as possible in the packet.
/// \param NewVal The data to store in the packet.
void TS::Packet::FillFree( std::string & NewVal ) {
int Offset = 188 - Free;
std::copy( NewVal.begin(), NewVal.begin() + Free, Buffer + Offset );
NewVal.erase(0,Free);
Free = 0;
}
/// Adds NumBytes of stuffing to the TS::Packet.
/// \param NumBytes the amount of stuffing bytes.
void TS::Packet::AddStuffing( int NumBytes ) {
if( NumBytes <= 0 ) { return; }
if( AdaptationField( ) == 3 ) {
int Offset = Buffer[4];
Buffer[4] = Offset + NumBytes - 1;
for( int i = 0; i < ( NumBytes -2 ); i ++ ) {
Buffer[6+Offset+i] = 0xFF;
}
Free -= NumBytes;
} else {
AdaptationField( 3 );
Buffer[4] = NumBytes - 1;
Buffer[5] = 0x00;
for( int i = 0; i < ( NumBytes -2 ); i ++ ) {
Buffer[6+i] = 0xFF;
}
Free -= NumBytes;
}
}
/// Transforms this TS::Packet into a standard Service Description Table
void TS::Packet::FFMpegHeader( ) {
static int MyCntr = 0;
std::copy( TS::SDT, TS::SDT + 188, Buffer );
ContinuityCounter( MyCntr );
Free = 0;
MyCntr = ( (MyCntr + 1) % 0x10);
}
int TS::Packet::ProgramMapPID( ) {
if( PID() != 0 ) { return -1; }
int Offset = Buffer[4];
int ProgramNumber = ( Buffer[13+Offset] << 8 ) + Buffer[14+Offset];
if( ProgramNumber == 0 ) { return -1; }
return ((Buffer[15+Offset] & 0x1F) << 8 ) + Buffer[16+Offset];
}
void TS::Packet::UpdateStreamPID( int & VideoPid, int & AudioPid ) {
int Offset = Buffer[4] + 5;
int SectionLength = ( ( Buffer[1+Offset] & 0x0F) << 8 ) + Buffer[2+Offset];
int ProgramInfoLength = ( (Buffer[10+Offset] & 0x0F) << 8 ) + Buffer[11+Offset];
int CurOffset = 12 + ProgramInfoLength;
while( CurOffset < (SectionLength+3)-4 ) {
if( Buffer[CurOffset] == 0x1B ) {
VideoPid = ((Buffer[CurOffset+1] & 0x1F) << 8 ) + Buffer[CurOffset+2];
fprintf( stderr, "Video stream recognized at PID %d\n", ((Buffer[CurOffset+1] & 0x1F) << 8 ) + Buffer[CurOffset+2] );
} else if( Buffer[CurOffset] == 0x0F ) {
AudioPid = ((Buffer[CurOffset+1] & 0x1F) << 8 ) + Buffer[CurOffset+2];
fprintf( stderr, "Audio stream recognized at PID %d\n", ((Buffer[CurOffset+1] & 0x1F) << 8 ) + Buffer[CurOffset+2] );
} else {
fprintf( stderr, "Unsupported stream type: %0.2X\n", Buffer[CurOffset] );
}
int ESLen = (( Buffer[CurOffset+3] & 0x0F ) << 8 ) + Buffer[CurOffset+4];
CurOffset += ( 5 + ESLen );
}
}
int TS::Packet::PESTimeStamp( ) {
if( !UnitStart( ) ) { return -1; }
int PesOffset = 4;
if( AdaptationField( ) >= 2 ) { PesOffset += 1 + AdaptationFieldLen( ); }
fprintf( stderr, "PES Offset: %d\n", PesOffset );
fprintf( stderr, "PES StartCode: %0.2X %0.2X %0.2X\n", Buffer[PesOffset], Buffer[PesOffset+1], Buffer[PesOffset+2] );
int MyTimestamp = (Buffer[PesOffset+9] & 0x0F) >> 1;
MyTimestamp = (MyTimestamp << 8) + Buffer[PesOffset+10];
MyTimestamp = (MyTimestamp << 7) + ((Buffer[PesOffset+11]) >> 1);
MyTimestamp = (MyTimestamp << 8) + Buffer[PesOffset+12];
MyTimestamp = (MyTimestamp << 7) + ((Buffer[PesOffset+13]) >> 1);
fprintf( stderr, "PES Timestamp: %d\n", MyTimestamp );
return MyTimestamp;
}
int TS::Packet::GetDataOffset( ) {
int Offset = 4;
if( AdaptationField( ) >= 2 ) {
Offset += 1 + AdaptationFieldLen( );
}
if( UnitStart() ) {
Offset += 8;//Default Header + Flag Bytes
Offset += 1 + Buffer[Offset];//HeaderLengthByte + HeaderLength
}
return Offset;
}
void TS::Packet::toDTSC( std::string Type, DTSC::DTMI & CurrentDTSC ) {
if( !CurrentDTSC.getContentP( "datatype" ) ) {
CurrentDTSC.addContent( DTSC::DTMI("datatype", Type ) );
}
if( Type == "video" ) {
if ( (RandomAccess() > 0) ){
if( !CurrentDTSC.getContentP( "keyframe" ) && !CurrentDTSC.getContentP( "interframe" ) ) {
CurrentDTSC.addContent(DTSC::DTMI("keyframe", 1));
}
} else {
if( !CurrentDTSC.getContentP( "keyframe" ) && !CurrentDTSC.getContentP( "interframe" ) ) {
CurrentDTSC.addContent(DTSC::DTMI("interframe", 1));
}
}
}
if( Type == "audio" ) {
if( ( RandomAccess() > 0 ) ) {
if( !CurrentDTSC.getContentP( "keyframe" ) && !CurrentDTSC.getContentP( "interframe" ) ) {
CurrentDTSC.addContent(DTSC::DTMI("keyframe", 1));
}
}
}
if( UnitStart() ) {
if( !CurrentDTSC.getContentP( "time" ) ) {
if( Type == "audio" ) {
CurrentDTSC.addContent( DTSC::DTMI( "time", PESTimeStamp( ) / 81000 ) );
} else {
CurrentDTSC.addContent( DTSC::DTMI( "time", ( PESTimeStamp( ) / 27000 ) - 700 ) );
//CurrentDTSC.addContent( DTSC::DTMI( "time", (PESTimeStamp( ) / 27000000) / 91 ) );
}
}
}
if( Type == "video" ) {
if( !CurrentDTSC.getContentP( "nalu" ) ) {
CurrentDTSC.addContent( DTSC::DTMI( "nalu", 1 ) );
}
if( !CurrentDTSC.getContentP( "offset" ) ) {
CurrentDTSC.addContent( DTSC::DTMI( "offset", 0 ) );
}
}
int DataOffset = GetDataOffset();
std::string ToAppend = std::string((char*)Buffer+DataOffset, (size_t)188-DataOffset);
std::string CurrentData;
if( CurrentDTSC.getContentP( "data" ) ) {
CurrentData = CurrentDTSC.getContent( "data" ).StrValue( );
}
CurrentDTSC.addContent(DTSC::DTMI("data", CurrentData + ToAppend ));
}

View file

@ -1,153 +0,0 @@
/// \file ts_packet.h
/// Holds all headers for the TS Namespace.
#pragma once
#include <string>
#include <cmath>
#include <stdint.h> //for uint64_t
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include "dtsc.h"
/// Holds all TS processing related code.
namespace TS {
/// Class for reading and writing TS Streams
class Packet {
public:
Packet();
~Packet();
bool FromString( std::string & Data );
void PID( int NewPID );
int PID();
void ContinuityCounter( int NewContinuity );
int ContinuityCounter();
void Clear();
void PCR( int64_t NewVal );
int64_t PCR();
void AdaptationField( int NewVal );
int AdaptationField( );
int AdaptationFieldLen( );
void DefaultPAT();
void DefaultPMT();
int UnitStart( );
void UnitStart( int NewVal );
int RandomAccess( );
void RandomAccess( int NewVal );
int BytesFree();
void Print();
std::string ToString();
void PESVideoLeadIn( int NewLen );
void PESAudioLeadIn( int NewLen, uint64_t PTS = 0 );
void FillFree( std::string & PackageData );
void AddStuffing( int NumBytes );
void FFMpegHeader( );
int PESTimeStamp( );
int GetDataOffset( );
//For output to DTSC
int ProgramMapPID( );
void UpdateStreamPID( int & VideoPid, int & AudioPid );
//DTSC::DTMI toDTSC(DTSC::DTMI & metadata, std::string Type);
void toDTSC( std::string Type, DTSC::DTMI & CurrentDTSC );
private:
int Free;
char Buffer[188];///< The actual data
};//TS::Packet class
/// Constructs an audio header to be used on each audio frame.
/// The length of this header will ALWAYS be 7 bytes, and has to be
/// prepended on each audio frame.
/// \param FrameLen the length of the current audio frame.
static inline std::string GetAudioHeader( int FrameLen ) {
char StandardHeader[7] = {0xFF,0xF1,0x4C,0x80,0x00,0x1F,0xFC};
FrameLen += 7;
StandardHeader[3] = ( StandardHeader[3] & 0xFC ) + ( ( FrameLen & 0x00001800 ) >> 11 );
StandardHeader[4] = ( ( FrameLen & 0x000007F8 ) >> 3 );
StandardHeader[5] = ( StandardHeader[5] & 0x3F ) + ( ( FrameLen & 0x00000007 ) << 5 );
return std::string(StandardHeader,7);
}
/// A standard Program Association Table, as generated by FFMPEG.
/// Seems to be independent of the stream.
static char PAT[188] = {
0x47,0x40,0x00,0x10, 0x00,0x00,0xB0,0x0D, 0x00,0x01,0xC1,0x00, 0x00,0x00,0x01,0xF0,
0x00,0x2A,0xB1,0x04, 0xB2,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF
};
/// A standard Program Mapping Table, as generated by FFMPEG.
/// Contains both Audio and Video mappings, works also on video- or audio-only streams.
static char PMT[188] = {
0x47,0x50,0x00,0x10, 0x00,0x02,0xB0,0x1D, 0x00,0x01,0xC1,0x00, 0x00,0xE1,0x00,0xF0,
0x00,0x1B,0xE1,0x00, 0xF0,0x00,0x0F,0xE1, 0x01,0xF0,0x06,0x0A, 0x04,0x65,0x6E,0x67,
0x00,0x8D,0x82,0x9A, 0x07,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF
};
/// A standard Sevice Description Table, as generated by FFMPEG.
/// Not used in our connector, provided for compatibility means
static char SDT[188] = {
0x47,0x40,0x11,0x10, 0x00,0x42,0xF0,0x25, 0x00,0x01,0xC1,0x00, 0x00,0x00,0x01,0xFF,
0x00,0x01,0xFC,0x80, 0x14,0x48,0x12,0x01, 0x06,0x46,0x46,0x6D, 0x70,0x65,0x67,0x09,
0x53,0x65,0x72,0x76, 0x69,0x63,0x65,0x30, 0x31,0xA7,0x79,0xA0, 0x03,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF
};
/// A standard Picture Parameter Set, as generated by FFMPEG.
/// Seems to be stream-independent.
static char PPS[24] = {
0x00,0x00,0x00,0x01,
0x27,0x4D,0x40,0x1F,
0xA9,0x18,0x0A,0x00,
0xB7,0x60,0x0D,0x40,
0x40,0x40,0x4C,0x2B,
0x5E,0xF7,0xC0,0x40
};
/// A standard Sequence Parameter Set, as generated by FFMPEG.
/// Seems to be stream-independent.
static char SPS[8] = {
0x00,0x00,0x00,0x01,
0x28,0xCE,0x09,0xC8
};
/// The full Bytesteam Nal-Header.
static char NalHeader[4] = {
0x00,0x00,0x00,0x01
};
/// The shortened Bytesteam Nal-Header.
static char ShortNalHeader[3] = {
0x00,0x00,0x01
};
};//TS namespace