ZLMediaKit/src/MedaiFile/TSMaker.h
2017-04-01 16:35:56 +08:00

250 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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字段存在11PTD和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_ */