tsMuxer/tsMuxer/tsPacket.h

627 lines
20 KiB
C++

#ifndef __TS_PACKET_H
#define __TS_PACKET_H
#include <memory.h>
#include <types/types.h>
#include <map>
#include "bitStream.h"
#include "vod_common.h"
// H.222 Table 2-45 - Program and program element descriptor
enum class TSDescriptorTag
{
// Bu-ray specifications
HDMV = 0x05, // HDMV registration descriptor
COPY_CONTROL = 0x88, // ATSC_CA_descriptor
// IUT Rec. H.222
REGISTRATION = 0x05, // registration_descriptor
CAS = 0x09, // CA_descriptor
LANG = 0x0A, // ISO_639_language_descriptor
AAC4 = 0x1C, // MPEG-4_AAC_audio_descriptor
AVC = 0x28, //
AAC2 = 0x2B, // MPEG-2_AAC_audio_descriptor
HEVC = 0x38,
VVC = 0x39,
DTS = 0x73,
LPCM = 0x80,
AC3 = 0x81,
EAC3 = 0xCC
};
const static int SYSTEM_START_CODE = 0xb9;
static const int DEFAULT_PCR_PID = 4097;
static const int DEFAULT_PMT_PID = 256;
// IUT Rec. H.222 Table 2-22 - Stream_id assignments
enum PesStreamId
{
PES_INT_SUB_ID = 0x20,
PES_INT_AC3_ID = 0x80,
PES_INT_DTS_ID = 0x8a,
PES_PROGRAM_STREAM_MAP = 0xbc,
PES_PRIVATE_DATA1 = 0xbd,
PADDING_STREAM = 0xbe,
PES_PRIVATE_DATA2 = 0xbf,
LPCM_ID = 0xa0,
PES_AUDIO_ID = 0xc0,
PES_VIDEO_ID = 0xe0,
PES_HEVC_ID = 0xe1,
PES_VVC_ID = 0xe1,
PES_VC1_ID = 0xfd,
PROGRAM_STREAM_DIRECTORY = 0xff
};
enum class StreamType
{
// Blu-ray Disk Specifiction Table 5-22 - stream_coding_type
VIDEO_MPEG2 = 0x02, // MPEG-2 video stream for Primary / Secondary video
VIDEO_H264 = 0x1b, // MPEG-4 AVC video stream for Primary / Secondary video
VIDEO_MVC = 0x20, // forbidden (Used for ProgramInfo_SS() in 5.4.7.6)
VIDEO_H265 = 0x24, // MPEG-H HEVC video stream for Primary / Secondary video
VIDEO_VC1 = 0xea, // SMPTE VC-1 video stream for Primary / Secondary video
AUDIO_LPCM = 0x80, // HDMV LPCM audio stream for Primary audio
AUDIO_AC3 = 0x81, // Dolby Digital (AC-3) audio stream for Primary audio
AUDIO_DTS = 0x82, // DTS audio stream for Primary audio
AUDIO_TRUE_HD = 0x83, // Dolby Lossless audio stream for Primary audio
AUDIO_EAC3 = 0x84, // Dolby Digital Plus audio stream for Primary audio
AUDIO_DTS_HD = 0x85, // DTS-HD audio stream except XLL for Primary audio
AUDIO_DTS_HD_MA = 0x86, // DTS-HD audio stream XLL for Primary audio
AUDIO_DRA = 0x87, // DRA audio stream for Primary audio
AUDIO_DRA_EXT = 0x88, // DRA Extension audio stream for Primary audio
AUDIO_EAC3_SECONDARY = 0xA1, // Dolby Digital Plus audio stream for Secondary audio
AUDIO_DTS_HD_SECONDARY = 0xA2, // DTS-HD audio stream for Secondary audio stream
SUB_PGS = 0x90, // Presentation Graphics stream
SUB_IGS = 0x91, // Interactive Graphics stream
SUB_TGS = 0x92, // Text subtitle stream
// IUT-T REC. H.222 | ISO/IEC 13818-1 Table 2-34 - Stream type assignments
RESERVED = 0x00, // ITU-T | ISO/IEC Reserved
VIDEO_MPEG1 = 0x01, // ISO/IEC 11172-2 Video
AUDIO_MPEG1 = 0x03, // ISO/IEC 11172-3 Audio
AUDIO_MPEG2 = 0x04, // ISO/IEC 13818-3 Audio
PRIVATE_SECTION = 0x05, // private_sections
PRIVATE_DATA = 0x06, // PES packets containing private data
AUDIO_AAC = 0x0f, // ISO/IEC 13818-7 Audio with ADTS transport syntax
VIDEO_MPEG4 = 0x10, // ISO/IEC 14496-2 Visual
AUDIO_AAC_RAW = 0x11, // ISO/IEC 14496-3 Audio with the LATM transport syntax
VIDEO_SUB_H265 = 0x25, // HEVC temporal video subset, profile as per of H265 Annex A
AUDIO_MHAS_MAIN = 0x2d, // ISO/IEC 23008-3 Audio with MHAS transport syntax _ main stream
AUDIO_MHAS_AUX = 0x2e, // ISO/IEC 23008-3 Audio with MHAS transport syntax - auxiliary stream
VIDEO_H266 = 0x33, // VVC video stream, profile as per H266 Annex A
// ATSC
VIDEO_DCII_ATSC = 0x80, // DigiCipher II video, identical to ITU-T Rec. H.262
AUDIO_AC3_ATSC = 0x81, // E-AC-3 A/52:2018
SUB_SCTE27_ATSC = 0x82, // SCTE-27 Subtitling
DATA_ISOCH_ATSC = 0x83, // SCTE-19 Isochronous data | Reserved
AUDIO_EAC3_ATSC = 0x87, // E-AC-3 A/52:2018
AUDIO_DTS_ATSC = 0x88, // E-AC-3 A / 107(ATSC 2.0)
// DVB
SUB_DVB = 0x06, // DVB Subtitles
};
struct AdaptiveField
{
static const unsigned ADAPTIVE_FIELD_LEN = 2;
unsigned int length : 8;
unsigned int afExtension : 1; // Adaptation field extension flag
unsigned int transportPrivateData : 1;
unsigned int splicingPoint : 1;
unsigned int opcrExist : 1;
unsigned int pcrExist : 1;
unsigned int priorityIndicator : 1;
unsigned int randomAccessIndicator : 1;
unsigned int discontinuityIndicator : 1;
inline unsigned getPCR32()
{
auto pcr = (uint32_t*)((uint8_t*)this + ADAPTIVE_FIELD_LEN);
return my_ntohl(*pcr);
// return my_ntohl(*pcr) * 0.95;
}
inline uint64_t getPCR33()
{
auto pcr = (uint32_t*)((uint8_t*)this + ADAPTIVE_FIELD_LEN);
auto pcrLo = (uint8_t*)this + ADAPTIVE_FIELD_LEN + sizeof(uint32_t);
return ((uint64_t)(my_ntohl(*pcr)) << 1) + (*pcrLo >> 7);
}
inline void setPCR33(uint64_t value)
{
auto pcr = (uint32_t*)((uint8_t*)this + ADAPTIVE_FIELD_LEN);
*pcr = my_htonl((uint32_t)(value >> 1));
auto pcrLo = (uint8_t*)this + ADAPTIVE_FIELD_LEN + sizeof(uint32_t);
pcrLo[0] = (((uint8_t)value & 1) << 7) + 0x7e;
pcrLo[1] = 0; // 41-42 bits of pcr
}
};
static const double PCR_HALF_FREQUENCY_AT_MKS = PCR_HALF_FREQUENCY / 1.0e6;
struct TSPacket
{
// static const unsigned TS_FRAME_SIZE = 188;
static const unsigned PCR_HALF_FREQUENCY_AT_MS = PCR_HALF_FREQUENCY / 1000;
static const unsigned TS_FRAME_SYNC_BYTE = 0x47;
static const unsigned TS_HEADER_SIZE = 4;
static const unsigned DATA_EXIST_BIT_VAL = 0x10000000;
static const unsigned PCR_BIT_VAL = 0x1000;
unsigned int syncByte : 8;
unsigned int PIDHi : 5;
unsigned int priority : 1;
unsigned int payloadStart : 1;
unsigned int tei : 1; // Transport Error Indicator
unsigned int PIDLow : 8;
/*
unsigned int sc: 2; // scrambling control
unsigned int afExists: 1; // adaptive field exist
unsigned int dataExists: 1;
unsigned int counter: 4; //Continuity counter
*/
unsigned int counter : 4; // Continuity counter
unsigned int dataExists : 1;
unsigned int afExists : 1; // adaptive field exist
unsigned int sc : 2; // scrambling control
inline uint16_t getPID() { return (uint16_t)(PIDHi << 8) + PIDLow; }
inline void setPID(uint16_t pid)
{
PIDHi = pid >> 8;
PIDLow = pid & 0xff;
}
inline unsigned getHeaderSize() { return TS_HEADER_SIZE + (afExists ? adaptiveField.length + 1 : 0); }
static inline uint32_t getPCRDif32(uint32_t nextPCR, uint32_t curPCR)
{
if (nextPCR >= curPCR)
return nextPCR - curPCR;
else
return nextPCR + (UINT_MAX - curPCR);
}
static inline int64_t getPCRDif33(int64_t nextPCR, int64_t curPCR)
{
if (nextPCR >= curPCR)
return nextPCR - curPCR;
else if (nextPCR < 0x40000000LL && curPCR > 0x1c0000000LL)
return nextPCR + (0x1ffffffffLL - curPCR) + 1;
else
return nextPCR - curPCR;
// return -(curPCR - nextPCR);
}
AdaptiveField adaptiveField;
};
class AbstractStreamReader;
struct BluRayCoarseInfo
{
uint32_t m_coarsePts;
uint32_t m_fineRefID;
uint32_t m_pktCnt;
BluRayCoarseInfo(uint32_t coarsePts, uint32_t fineRefID, uint32_t pktCnt)
: m_coarsePts(coarsePts), m_fineRefID(fineRefID), m_pktCnt(pktCnt)
{
}
};
struct PMTIndexData
{
uint32_t m_pktCnt;
int64_t m_frameLen;
PMTIndexData(uint32_t pktCnt, int64_t frameLen) : m_pktCnt(pktCnt), m_frameLen(frameLen) {}
};
typedef std::map<uint64_t, PMTIndexData> PMTIndex;
struct PMTStreamInfo
{
PMTStreamInfo()
: m_streamType(),
m_pid(0),
m_esInfoLen(0),
m_pmtPID(-1),
m_esInfoData(),
m_lang(),
isSecondary(false),
m_codecReader()
{
}
PMTStreamInfo(StreamType streamType, int pid, uint8_t* esInfoData, int esInfoLen, AbstractStreamReader* codecReader,
const std::string& lang, bool secondary)
{
m_streamType = streamType;
m_pid = pid;
memcpy(m_esInfoData, esInfoData, esInfoLen);
m_esInfoLen = esInfoLen;
m_codecReader = codecReader;
memset(m_lang, 0, sizeof(m_lang));
memcpy(m_lang, lang.c_str(), lang.size() < 3 ? lang.size() : 3);
m_pmtPID = -1;
isSecondary = secondary;
}
virtual ~PMTStreamInfo() {}
StreamType m_streamType;
int m_pid;
int m_esInfoLen;
int m_pmtPID;
uint8_t m_esInfoData[128];
char m_lang[4];
bool isSecondary;
// ---------------------
std::vector<PMTIndex> m_index; // blu-ray seek index. key=number of tsFrame. value=information about key frame
AbstractStreamReader* m_codecReader;
};
typedef std::map<int, PMTStreamInfo> PIDListMap;
struct TS_program_map_section
{
int video_pid;
int video_type;
int audio_pid;
int audio_type;
int sub_pid;
int pcr_pid;
int casPID;
int casID;
int program_number;
// std::vector<PMTStreamInfo> pidList;
PIDListMap pidList;
TS_program_map_section();
bool deserialize(uint8_t* buffer, int buf_size);
static bool isFullBuff(uint8_t* buffer, int buf_size);
uint32_t serialize(uint8_t* buffer, int max_buf_size, bool blurayMode, bool hdmvDescriptors);
private:
void extractDescriptors(uint8_t* curPos, int es_info_len, PMTStreamInfo& pmtInfo);
void extractPMTDescriptors(uint8_t* curPos, int es_info_len);
// uint32_t tmpAvCrc[257];
};
struct TS_program_association_section
{
int transport_stream_id;
int m_nitPID;
std::map<int, int> pmtPids; // program pid, program number
TS_program_association_section();
bool deserialize(uint8_t* buffer, int buf_size);
uint32_t serialize(uint8_t* buffer, int buf_size);
private:
// uint32_t tmpAvCrc[257];
};
struct PS_stream_pack
{
bool deserialize(uint8_t* buffer, int buf_size);
uint64_t m_pts;
uint32_t m_pts_ext;
uint32_t m_program_mux_rate;
uint32_t m_pack_stuffing_length;
};
struct M2TSStreamInfo
{
M2TSStreamInfo()
: streamPID(0),
stream_coding_type(),
video_format(0),
frame_rate_index(3),
number_of_offset_sequences(0),
width(0),
height(0),
HDR(0),
aspect_ratio_index(0),
audio_presentation_type(0),
sampling_frequency_index(0),
character_code(0),
language_code(),
isSecondary(false)
{
}
M2TSStreamInfo(const PMTStreamInfo& pmtStreamInfo);
M2TSStreamInfo(const M2TSStreamInfo& other);
int streamPID;
StreamType stream_coding_type; // ts type
int video_format;
int frame_rate_index;
int number_of_offset_sequences;
int width;
int height;
int HDR;
int aspect_ratio_index;
int audio_presentation_type;
int sampling_frequency_index;
int character_code;
char language_code[4];
bool isSecondary;
std::vector<PMTIndex> m_index;
static void blurayStreamParams(double fps, bool interlaced, int width, int height, int ar, int* video_format,
int* frame_rate_index, int* aspect_ratio_index);
};
struct CLPIStreamInfo : public M2TSStreamInfo
{
CLPIStreamInfo(const PMTStreamInfo& pmtStreamInfo) : M2TSStreamInfo(pmtStreamInfo)
{
memset(country_code, 0, sizeof(country_code));
memset(copyright_holder, 0, sizeof(copyright_holder));
memset(recording_year, 0, sizeof(recording_year));
memset(recording_number, 0, sizeof(recording_number));
}
// int stream_coding_type;
// int video_format;
// int frame_rate_index;
// int aspect_ratio_index;
// bool cc_flag;
// int audio_presentation_type;
// int sampling_frequency;
// char language_code[4];
char country_code[3];
char copyright_holder[4];
char recording_year[3];
char recording_number[6];
void ISRC(BitStreamReader& reader);
void parseStreamCodingInfo(BitStreamReader& reader);
static void readString(char* dest, BitStreamReader& reader, int size)
{
for (int i = 0; i < size; i++) dest[i] = reader.getBits(8);
dest[size] = 0;
}
static void writeString(const char* dest, BitStreamWriter& writer, int size)
{
for (int i = 0; i < size; i++) writer.putBits(8, dest[i]);
}
CLPIStreamInfo() : M2TSStreamInfo()
{
memset(language_code, 0, sizeof(language_code));
memset(country_code, 0, sizeof(country_code));
memset(copyright_holder, 0, sizeof(copyright_holder));
memset(recording_year, 0, sizeof(recording_year));
memset(recording_number, 0, sizeof(recording_number));
}
void composeISRC(BitStreamWriter& writer) const;
void composeStreamCodingInfo(BitStreamWriter& writer) const;
private:
};
struct CLPIProgramInfo
{
uint32_t SPN_program_sequence_start;
uint16_t program_map_PID;
uint8_t number_of_streams_in_ps;
};
class CLPIParser
{
public:
CLPIParser()
: type_indicator(),
version_number(),
clip_stream_type(0),
application_type(0),
is_ATC_delta(false),
TS_recording_rate(0),
number_of_source_packets(0),
format_identifier(),
presentation_start_time(0),
presentation_end_time(0),
m_clpiNum(0),
isDependStream(false)
{
}
void parse(uint8_t* buffer, int64_t len);
bool parse(const char* fileName);
int compose(uint8_t* buffer, int bufferSize);
std::vector<CLPIProgramInfo> m_programInfo;
std::vector<CLPIProgramInfo> m_programInfoMVC;
char type_indicator[5];
char version_number[5];
std::map<int, CLPIStreamInfo> m_streamInfo;
std::map<int, CLPIStreamInfo> m_streamInfoMVC;
uint8_t clip_stream_type;
uint8_t application_type;
bool is_ATC_delta;
uint32_t TS_recording_rate;
uint32_t number_of_source_packets;
char format_identifier[5];
uint32_t presentation_start_time;
uint32_t presentation_end_time;
size_t m_clpiNum;
std::vector<uint32_t> SPN_extent_start;
std::vector<int32_t> interleaveInfo;
bool isDependStream;
private:
void HDMV_LPCM_down_mix_coefficient(uint8_t* buffer, int dataLength);
void Extent_Start_Point(uint8_t* buffer, int dataLength);
void ProgramInfo_SS(uint8_t* buffer, int dataLength);
void CPI_SS(uint8_t* buffer, int dataLength);
private:
void parseProgramInfo(uint8_t* buffer, uint8_t* end, std::vector<CLPIProgramInfo>& programInfo,
std::map<int, CLPIStreamInfo>& streamInfo);
void parseSequenceInfo(uint8_t* buffer, uint8_t* end);
void parseCPI(uint8_t* buffer, uint8_t* end);
void EP_map(BitStreamReader& reader);
void parseClipMark(uint8_t* buffer, uint8_t* end);
void parseClipInfo(BitStreamReader& reader);
void parseExtensionData(uint8_t* buffer, uint8_t* end);
void TS_type_info_block(BitStreamReader& reader);
void composeProgramInfo(BitStreamWriter& writer, bool isSsExt);
void composeTS_type_info_block(BitStreamWriter& writer);
void composeClipInfo(BitStreamWriter& writer);
void composeSequenceInfo(BitStreamWriter& writer);
void composeCPI(BitStreamWriter& writer, bool isCPIExt);
void composeClipMark(BitStreamWriter& writer);
void composeExtentInfo(BitStreamWriter& writer);
void composeExtentStartPoint(BitStreamWriter& writer);
void composeEP_map(BitStreamWriter& writer, bool isSSExt);
std::vector<BluRayCoarseInfo> buildCoarseInfo(M2TSStreamInfo& streamInfo);
void composeEP_map_for_one_stream_PID(BitStreamWriter& writer, M2TSStreamInfo& streamInfo);
};
struct MPLSStreamInfo : public M2TSStreamInfo
{
MPLSStreamInfo();
MPLSStreamInfo(const PMTStreamInfo& pmtStreamInfo);
MPLSStreamInfo(const MPLSStreamInfo& other);
~MPLSStreamInfo();
void parseStreamAttributes(BitStreamReader& reader);
void parseStreamEntry(BitStreamReader& reader);
void composeStreamAttributes(BitStreamWriter& reader);
void composeStreamEntry(BitStreamWriter& reader, size_t entryNum, int subPathID = 0);
void composePGS_SS_StreamEntry(BitStreamWriter& writer, size_t entryNum);
public:
int type;
uint8_t character_code;
uint8_t offsetId;
bool isSSPG;
int SS_PG_offset_sequence_id;
MPLSStreamInfo* leftEye; // used for stereo PG
MPLSStreamInfo* rightEye;
PIPParams pipParams;
};
struct MPLSPlayItem
{
uint32_t IN_time = 0;
uint32_t OUT_time = 0;
std::string fileName;
int connection_condition = 0;
};
struct PlayListMark
{
int m_playItemID;
uint32_t m_markTime;
PlayListMark(int playItemID, uint32_t markTime) : m_playItemID(playItemID), m_markTime(markTime) {}
};
struct ExtDataBlockInfo
{
ExtDataBlockInfo(uint8_t* a_data, int a_dataLen, int a_id1, int a_id2) : id1(a_id1), id2(a_id2)
{
data.resize(a_dataLen);
if (!data.empty())
memcpy(&data[0], a_data, data.size());
}
std::vector<uint8_t> data;
int id1;
int id2;
};
struct MPLSParser
{
MPLSParser();
bool parse(const char* fileName);
void parse(uint8_t* buffer, int len);
int compose(uint8_t* buffer, int bufferSize, DiskType dt);
MPLSStreamInfo getStreamByPID(int pid) const;
std::vector<MPLSStreamInfo> getPgStreams() const;
int PlayList_playback_type;
int playback_count;
int number_of_SubPaths;
bool is_multi_angle;
int ref_to_STC_id;
bool PlayItem_random_access_flag;
int number_of_angles;
bool is_different_audios;
bool is_seamless_angle_change;
int m_chapterLen;
uint32_t IN_time;
uint32_t OUT_time;
std::vector<MPLSPlayItem> m_playItems;
std::vector<MPLSStreamInfo> m_streamInfo;
std::vector<MPLSStreamInfo> m_streamInfoMVC;
std::vector<PlayListMark> m_marks;
int m_m2tsOffset;
bool isDependStreamExist;
bool mvc_base_view_r;
int subPath_type;
int number_of_primary_video_stream_entries;
int number_of_primary_audio_stream_entries;
int number_of_PG_textST_stream_entries;
int number_of_IG_stream_entries;
int number_of_secondary_audio_stream_entries;
int number_of_secondary_video_stream_entries;
int number_of_PiP_PG_textST_stream_entries_plus;
int number_of_DolbyVision_video_stream_entries;
std::vector<std::string> m_mvcFiles;
private:
void composeSubPlayItem(BitStreamWriter& writer, size_t playItemNum, size_t subPathNum,
std::vector<PMTIndex>& pmtIndexList);
void composeSubPath(BitStreamWriter& writer, size_t subPathNum, std::vector<PMTIndex>& pmtIndexList, int type);
int composePip_metadata(uint8_t* buffer, int bufferSize, std::vector<PMTIndex>& pmtIndexList);
void composeExtensionData(BitStreamWriter& writer, std::vector<ExtDataBlockInfo>& extDataBlockInfo);
void parseExtensionData(uint8_t* data, uint8_t* dataEnd);
void SubPath_extension(BitStreamWriter& writer);
void parseStnTableSS(uint8_t* data, int dataLength);
void AppInfoPlayList(BitStreamReader& reader);
void composeAppInfoPlayList(BitStreamWriter& writer);
void UO_mask_table(BitStreamReader& reader);
void parsePlayList(uint8_t* buffer, int len);
void parsePlayItem(BitStreamReader& reader, int PlayItem_id);
void parsePlayListMark(uint8_t* buffer, int len);
void STN_table(BitStreamReader& reader, int PlayItem_id);
void composePlayList(BitStreamWriter& writer);
// void composePlayItem(BitStreamWriter& writer);
void composePlayItem(BitStreamWriter& writer, size_t playItemNum, std::vector<PMTIndex>& pmtIndexList);
void composePlayListMark(BitStreamWriter& writer);
void composeSTN_table(BitStreamWriter& writer, size_t PlayItem_id, bool isSSEx);
int composeSTN_tableSS(uint8_t* buffer, int bufferSize);
int composeSubPathEntryExtension(uint8_t* buffer, int bufferSize);
int composeUHD_metadata(uint8_t* buffer, int bufferSize);
MPLSStreamInfo& getMainStream();
MPLSStreamInfo& getMVCDependStream();
int calcPlayItemID(MPLSStreamInfo& streamInfo, uint32_t pts);
int pgIndexToFullIndex(int value);
void parseSubPathEntryExtension(uint8_t* data, int dataLen);
};
#endif