mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-01 17:11:31 +08:00
250 lines
12 KiB
C++
250 lines
12 KiB
C++
/*
|
||
* TSMaker.h
|
||
*
|
||
* Created on: 2013-6-21
|
||
* Author: root
|
||
*/
|
||
|
||
#ifndef TSMAKER_H_
|
||
#define TSMAKER_H_
|
||
|
||
#include "CRC/crc32.h"
|
||
#include <string>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <iostream>
|
||
#include <string.h>
|
||
#include "Util/File.h"
|
||
using namespace std;
|
||
using namespace ZL::Util;
|
||
|
||
|
||
#define TS_PACKET_SIZE 188
|
||
#define TS_PACKET_HEADER 4
|
||
#define TS_SYNC_BYTE 0x47
|
||
#define TS_PAT_PID 0x00
|
||
#define TS_PMT_PID 0xFFF
|
||
#define TS_H264_PID 0x100
|
||
#define TS_AAC_PID 0x101
|
||
#define TS_H264_STREAM_ID 0xE0
|
||
#define TS_AAC_STREAM_ID 0xC0
|
||
#define PMT_STREAM_TYPE_VIDEO 0x1B
|
||
#define PMT_STREAM_TYPE_AUDIO 0x0F
|
||
|
||
//#define ES_BUF_SIZE 256*1024
|
||
|
||
//ts 包头
|
||
typedef struct Tag_PacketHeader {
|
||
unsigned char sync_byte :8; //同步字节, 固定为0x47,表示后面的是一个TS分组
|
||
unsigned char tras_error :1; //传输误码指示符
|
||
unsigned char play_init :1; //有效荷载单元起始指示符
|
||
unsigned char tras_prio :1; //传输优先, 1表示高优先级,传输机制可能用到,解码用不着
|
||
unsigned int PID :13; //PID
|
||
unsigned char tras_scramb :2; //传输加扰控制
|
||
unsigned char ada_field_C :2; //自适应控制 01仅含有效负载,10仅含调整字段,11含有调整字段和有效负载,先调整字段然后有效负载。为00解码器不进行处理
|
||
unsigned char conti_cter :4; //连续计数器 一个4bit的计数器,范围0-15
|
||
} TsPacketHeader;
|
||
|
||
//连续性计数器,也就是说 有多少个 pat包,几个pmt包 ,几个MP3 包,几个 h264包,0x00 - 0x0f ,然后折回到0x00
|
||
typedef struct Tag_Continuity_Counter {
|
||
unsigned char continuity_counter_pat;
|
||
unsigned char continuity_counter_pmt;
|
||
unsigned char continuity_counter_video;
|
||
unsigned char continuity_counter_audio;
|
||
} Continuity_Counter;
|
||
|
||
//自适应段标志
|
||
typedef struct Tag_Ts_Adaptation_field {
|
||
unsigned char discontinuty_indicator :1; //1表明当前传送流分组的不连续状态为真
|
||
unsigned char random_access_indicator :1; //表明下一个有相同PID的PES分组应该含有PTS字段和一个原始流访问点
|
||
unsigned char elementary_stream_priority_indicator :1; //优先级
|
||
unsigned char PCR_flag :1; //包含pcr字段
|
||
unsigned char OPCR_flag :1; //包含opcr字段
|
||
unsigned char splicing_point_flag :1; //拼接点标志
|
||
unsigned char transport_private_data_flag :1; //私用字节
|
||
unsigned char adaptation_field_extension_flag :1; //调整字段有扩展
|
||
|
||
unsigned char adaptation_field_length; //自适应段长度
|
||
unsigned long long pcr; //自适应段中用到的的pcr
|
||
unsigned long long opcr; //自适应段中用到的的opcr
|
||
unsigned char splice_countdown;
|
||
unsigned char private_data_len;
|
||
unsigned char private_data[256];
|
||
} Ts_Adaptation_field;
|
||
|
||
//PAT结构体:节目相关表
|
||
typedef struct Tag_TsPat {
|
||
unsigned char table_id :8; //固定为0x00 ,标志是该表是PAT
|
||
unsigned char section_syntax_indicator :1; //段语法标志位,固定为1
|
||
unsigned char zero :1; //0
|
||
unsigned char reserved_1 :2; //保留位
|
||
unsigned int section_length :12; //表示这个字节后面有用的字节数,包括CRC32
|
||
unsigned int transport_stream_id :16; //该传输流的ID,区别于一个网络中其它多路复用的流
|
||
unsigned char reserved_2 :2; //保留位
|
||
unsigned char version_number :5; //范围0-31,表示PAT的版本号
|
||
unsigned char current_next_indicator :1; //发送的PAT是当前有效还是下一个PAT有效
|
||
unsigned char section_number :8; //分段的号码。PAT可能分为多段传输,第一段为00,以后每个分段加1,最多可能有256个分段
|
||
unsigned char last_section_number :8; //最后一个分段的号码
|
||
unsigned int program_number :16; //节目号
|
||
unsigned char reserved_3 :3; //保留位
|
||
//unsigned int network_PID :13 ; //网络信息表(NIT)的PID,节目号为0时对应的PID为network_PID,本例中不含有 networke_pid
|
||
unsigned int program_map_PID :13; //节目映射表的PID,节目号大于0时对应的PID,每个节目对应一个
|
||
unsigned long long CRC_32 :32; //CRC32校验码
|
||
} TsPat;
|
||
|
||
//PMT结构体:节目映射表
|
||
typedef struct Tag_TsPmt {
|
||
unsigned char table_id :8; //固定为0x02, 表示PMT表
|
||
unsigned char section_syntax_indicator :1; //固定为0x01
|
||
unsigned char zero :1; //0x00
|
||
unsigned char reserved_1 :2; //0x03
|
||
unsigned int section_length :12; //首先两位bit置为00,它指示段的byte数,由段长度域开始,包含CRC。
|
||
unsigned int program_number :16; // 指出该节目对应于可应用的Program map PID
|
||
unsigned char reserved_2 :2; //0x03
|
||
unsigned char version_number :5; //指出TS流中Program map section的版本号
|
||
unsigned char current_next_indicator :1; //当该位置1时,当前传送的Program map section可用;当该位置0时,指示当前传送的Program map section不可用,下一个TS流的Program map section有效。
|
||
unsigned char section_number :8; //固定为0x00
|
||
unsigned char last_section_number :8; //固定为0x00
|
||
unsigned char reserved_3 :3; //0x07
|
||
unsigned int PCR_PID :13; //指明TS包的PID值,该TS包含有PCR域,该PCR值对应于由节目号指定的对应节目。如果对于私有数据流的节目定义与PCR无关,这个域的值将为0x1FFF。
|
||
unsigned char reserved_4 :4; //预留为0x0F
|
||
unsigned int program_info_length :12; //前两位bit为00。该域指出跟随其后对节目信息的描述的byte数。
|
||
unsigned char stream_type_video :8; //指示特定PID的节目元素包的类型。该处PID由elementary PID指定
|
||
unsigned char reserved_5_video :3; //0x07
|
||
unsigned int elementary_PID_video :13; //该域指示TS包的PID值。这些TS包含有相关的节目元素
|
||
unsigned char reserved_6_video :4; //0x0F
|
||
unsigned int ES_info_length_video :12; //前两位bit为00。该域指示跟随其后的描述相关节目元素的byte数
|
||
unsigned char stream_type_audio :8; //指示特定PID的节目元素包的类型。该处PID由elementary PID指定
|
||
unsigned char reserved_5_audio :3; //0x07
|
||
unsigned int elementary_PID_audio :13; //该域指示TS包的PID值。这些TS包含有相关的节目元素
|
||
unsigned char reserved_6_audio :4; //0x0F
|
||
unsigned int ES_info_length_audio :12; //前两位bit为00。该域指示跟随其后的描述相关节目元素的byte数
|
||
unsigned long long CRC_32 :32; //CRC32校验码
|
||
} TsPmt;
|
||
|
||
//PTS_DTS结构体:本程序设置都有 “11”
|
||
typedef struct Tag_TsPtsDts {
|
||
unsigned char reserved_1 :4;
|
||
unsigned char pts_32_30 :3; //显示时间戳
|
||
unsigned char marker_bit1 :1;
|
||
unsigned int pts_29_15 :15;
|
||
unsigned char marker_bit2 :1;
|
||
unsigned int pts_14_0 :15;
|
||
unsigned char marker_bit3 :1;
|
||
unsigned char reserved_2 :4;
|
||
unsigned char dts_32_30 :3; //解码时间戳
|
||
unsigned char marker_bit4 :1;
|
||
unsigned int dts_29_15 :15;
|
||
unsigned char marker_bit5 :1;
|
||
unsigned int dts_14_0 :15;
|
||
unsigned char marker_bit6 :1;
|
||
} TsPtsDts;
|
||
|
||
//PES包结构体,包括PES包头和ES数据 ,头 19 个字节
|
||
typedef struct Tag_TsPes {
|
||
unsigned int packet_start_code_prefix :24; //起始:0x000001
|
||
unsigned char stream_id :8; //基本流的类型和编号
|
||
unsigned int PES_packet_length :16; //包长度,就是帧数据的长度,可能为0,要自己算,做多16位,如果超出则需要自己算
|
||
unsigned char marker_bit :2; //必须是:'10'
|
||
unsigned char PES_scrambling_control :2; //pes包有效载荷的加扰方式
|
||
unsigned char PES_priority :1; //有效负载的优先级
|
||
unsigned char data_alignment_indicator :1; //如果设置为1表明PES包的头后面紧跟着视频或音频syncword开始的代码。
|
||
unsigned char copyright :1; //1:靠版权保护,0:不靠
|
||
unsigned char original_or_copy :1; //1;有效负载是原始的,0:有效负载时拷贝的
|
||
unsigned char PTS_DTS_flags :2; //'10':PTS字段存在,‘11’:PTD和DTS都存在,‘00’:都没有,‘01’:禁用。
|
||
unsigned char ESCR_flag :1; //1:escr基准字段 和 escr扩展字段均存在,0:无任何escr字段存在
|
||
unsigned char ES_rate_flag :1; //1:es_rate字段存在,0 :不存在
|
||
unsigned char DSM_trick_mode_flag :1; //1;8比特特接方式字段存在,0 :不存在
|
||
unsigned char additional_copy_info_flag :1; //1:additional_copy_info存在,0: 不存在
|
||
unsigned char PES_CRC_flag :1; //1:crc字段存在,0:不存在
|
||
unsigned char PES_extension_flag :1; //1:扩展字段存在,0:不存在
|
||
unsigned char PES_header_data_length :8; //后面数据的长度,
|
||
//TsPtsDts tsptsdts; //ptsdts结构体对象,10个字节
|
||
char *ES;
|
||
unsigned long ESlen;
|
||
} TsPes;
|
||
|
||
/*//H264一帧数据的结构体
|
||
typedef struct Tag_NALU_t {
|
||
unsigned char forbidden_bit; //! Should always be FALSE
|
||
unsigned char nal_reference_idc; //! NALU_PRIORITY_xxxx
|
||
unsigned char nal_unit_type; //! NALU_TYPE_xxxx
|
||
unsigned int startcodeprefix_len; //! 前缀字节数
|
||
unsigned int len; //! 包含nal 头的nal 长度,从第一个00000001到下一个000000001的长度
|
||
unsigned int max_size; //! 做多一个nal 的长度
|
||
unsigned char * buf; //! 包含nal 头的nal 数据
|
||
unsigned int lost_packets; //! 预留
|
||
} NALU_t;*/
|
||
|
||
//nal类型
|
||
typedef enum {
|
||
NALU_TYPE_SLICE = 1,
|
||
NALU_TYPE_DPA = 2,
|
||
NALU_TYPE_DPB = 3,
|
||
NALU_TYPE_DPC = 4,
|
||
NALU_TYPE_IDR = 5,
|
||
NALU_TYPE_SEI = 6,
|
||
NALU_TYPE_SPS = 7,
|
||
NALU_TYPE_PPS = 8,
|
||
NALU_TYPE_AUD = 9,
|
||
NALU_TYPE_EOSEQ = 10,
|
||
NALU_TYPE_EOSTREAM = 11,
|
||
NALU_TYPE_FILL = 12,
|
||
#if (MVC_EXTENSION_ENABLE)
|
||
NALU_TYPE_PREFIX = 14,
|
||
NALU_TYPE_SUB_SPS = 15,
|
||
NALU_TYPE_SLC_EXT = 20,
|
||
NALU_TYPE_VDRD = 24 // View and Dependency Representation Delimiter NAL Unit
|
||
#endif
|
||
} NaluType;
|
||
|
||
/*//MP3头结构体
|
||
typedef struct Tag_Mp3_Header {
|
||
unsigned int sync :11; //同步信息
|
||
unsigned char version :2; //版本
|
||
unsigned char layer :2; //层
|
||
unsigned char error_protection :1; //CRC校验
|
||
unsigned char bitrate_index :4; //位率
|
||
unsigned char sampling_frequency :2; //采样频率
|
||
unsigned char padding :1; //帧长调节
|
||
unsigned char private_t :1; //保留字
|
||
unsigned char mode :2; //声道模式
|
||
unsigned char mode_extension :2; //扩展模式
|
||
unsigned char copyright :1; //版权
|
||
unsigned char original :1; //原版标志
|
||
unsigned char emphasis :2; //强调模式
|
||
} Mp3_Header;*/
|
||
|
||
|
||
class TSMaker {
|
||
public:
|
||
TSMaker();
|
||
virtual ~TSMaker();
|
||
bool init(const string &strFilename, uint32_t ui32BufSize);
|
||
int inputH264(const char *pcData, uint32_t ui32Len, uint64_t ui64Time);
|
||
int inputAAC(const char *pcData, uint32_t ui32Len, uint64_t ui64Time);
|
||
void clear();
|
||
private:
|
||
string m_strFilename;
|
||
FILE *m_pOutVideoTs;
|
||
Continuity_Counter m_continuityCounter;
|
||
TsPes *m_pVideo_pes;
|
||
TsPes *m_pAudio_pes;
|
||
unsigned int m_uiWritePacketNum;
|
||
char *m_pcFileBuf;
|
||
|
||
void flush();
|
||
void CreateTsHeader(TsPacketHeader * pTsHeader, unsigned int uiPID, unsigned char ucPlayInit, unsigned char ucAdaFieldC);
|
||
void TsHeader2buffer(TsPacketHeader * pTsHeader, unsigned char *pucBuffer);
|
||
void CreatePAT();
|
||
void CreatePMT();
|
||
|
||
void WriteAdaptive_flags_Head(Ts_Adaptation_field * pAdaptationField, uint64_t ui64VideoPts);
|
||
void WriteAdaptive_flags_Tail(Ts_Adaptation_field * pAdaptationField); //填写自适应段标志帧尾的
|
||
|
||
void PES2TS(TsPes * pPes, unsigned int uiPID, Ts_Adaptation_field * pAdaptationField, uint64_t ui64Pts);
|
||
void CreateAdaptive_Ts(Ts_Adaptation_field * pAdaptationField, unsigned char * pcTs, unsigned int uiAdaptiveLength);
|
||
};
|
||
|
||
#endif /* TSMAKER_H_ */
|