├── README.md ├── TSParser.cpp ├── TSParser.h ├── demo.ts ├── main.cpp ├── makefile └── types.h /README.md: -------------------------------------------------------------------------------- 1 | # TSParser 2 | 一个解析MPEG-TS的小程序,解析PAT,PMT,PCR,PTS,DTS等信息 3 | 4 | ## Compile 5 | 6 | # cd TSParser 7 | # make 8 | 9 | ## Usage 10 | 11 | # ./tsparser 12 | Usage: ./tsparser file 13 | Demo : ./tsparser /home/demo.ts 14 | 15 | # ./tsparser demo.ts 16 | Open file success. -- [TSParser.cpp:479] 17 | Seek to first packet, offset: 0x00000000 -- [TSParser.cpp:430] 18 | PktNo: 00000000, Offset: 0x00000000, PID: 0x1FFF, CC: 00, Null Packet -- [TSParser.cpp:602] 19 | PktNo: 00000001, Offset: 0x000000BC, PID: 0x1FFF, CC: 01, Null Packet -- [TSParser.cpp:602] 20 | PktNo: 00000002, Offset: 0x00000178, PID: 0x1FFF, CC: 02, Null Packet -- [TSParser.cpp:602] 21 | PktNo: 00000003, Offset: 0x00000234, PID: 0x1FFF, CC: 03, Null Packet -- [TSParser.cpp:602] 22 | PktNo: 00000004, Offset: 0x000002F0, PID: 0x1FFF, CC: 04, Null Packet -- [TSParser.cpp:602] 23 | PktNo: 00000005, Offset: 0x000003AC, PID: 0x1FFF, CC: 05, Null Packet -- [TSParser.cpp:602] 24 | PktNo: 00000006, Offset: 0x00000468, PID: 0x1FFF, CC: 06, Null Packet -- [TSParser.cpp:602] 25 | PktNo: 00000007, Offset: 0x00000524, PID: 0x1FFF, CC: 07, Null Packet -- [TSParser.cpp:602] 26 | PktNo: 00000008, Offset: 0x000005E0, PID: 0x1FFF, CC: 08, Null Packet -- [TSParser.cpp:602] 27 | PktNo: 00000009, Offset: 0x0000069C, PID: 0x1FFF, CC: 09, Null Packet -- [TSParser.cpp:602] 28 | PktNo: 00000010, Offset: 0x00000758, PID: 0x1FFF, CC: 10, Null Packet -- [TSParser.cpp:602] 29 | PktNo: 00000011, Offset: 0x00000814, PID: 0x1FFF, CC: 11, Null Packet -- [TSParser.cpp:602] 30 | PktNo: 00000012, Offset: 0x000008D0, PID: 0x1FFF, CC: 12, Null Packet -- [TSParser.cpp:602] 31 | PktNo: 00000013, Offset: 0x0000098C, PID: 0x1FFF, CC: 13, Null Packet -- [TSParser.cpp:602] 32 | PktNo: 00000014, Offset: 0x00000A48, PID: 0x1FFF, CC: 14, Null Packet -- [TSParser.cpp:602] 33 | PktNo: 00000015, Offset: 0x00000B04, PID: 0x1FFF, CC: 15, Null Packet -- [TSParser.cpp:602] 34 | PktNo: 00000016, Offset: 0x00000BC0, PID: 0x0000, CC: 01, PAT -- [TSParser.cpp:602] 35 | PktNo: 00000017, Offset: 0x00000C7C, PID: 0x0500, CC: 01, PMT -- [TSParser.cpp:602] 36 | PktNo: 00000018, Offset: 0x00000D38, PID: 0x1023, CC: 00, PCR: 276(00:00:00.003), PTS: 738(00:00:00.008), DTS: 506(00:00:00.005), Video -- [TSParser.cpp:602] 37 | PktNo: 00000019, Offset: 0x00000DF4, PID: 0x1022, CC: 00, PTS: 562(00:00:00.006), Audio -- [TSParser.cpp:602] 38 | PktNo: 00000020, Offset: 0x00000EB0, PID: 0x1023, CC: 01, Video -- [TSParser.cpp:602] 39 | PktNo: 00000021, Offset: 0x00000F6C, PID: 0x1023, CC: 02, Video -- [TSParser.cpp:602] 40 | PktNo: 00000022, Offset: 0x00001028, PID: 0x1023, CC: 03, Video -- [TSParser.cpp:602] 41 | PktNo: 00000023, Offset: 0x000010E4, PID: 0x1023, CC: 04, Video -- [TSParser.cpp:602] 42 | ... 43 | Parse file complete! -- [TSParser.cpp:458] 44 | Close file -- [TSParser.cpp:497] 45 | -------------------------------------------------------------------------------- /TSParser.cpp: -------------------------------------------------------------------------------- 1 | #include "TSParser.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_READ_PKT_NUM 10000 7 | #define MAX_CHECK_PKT_NUM 3 8 | #define MAX_TIME_STR_LEN 20 9 | 10 | #define MK_WORD(high,low) (((high)<<8)|(low)) 11 | #define MK_PCR(b1,b2,b3,b4,b5) (((sint64)(b1)<<25)|((sint64)(b2)<<17)|((sint64)(b3)<<9)|((sint64)(b4)<<1)|(b5)) 12 | #define MK_PTS_DTS(b1,b2,b3,b4,b5) (((sint64)(b1)<<30)|((sint64)(b2)<<22)|((sint64)(b3)<<15)|((sint64)(b4)<<7)|(b5)) 13 | 14 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) 15 | #define RETURN_IF_NOT_OK(ret) if (TS_OK != ret) { return ret; } 16 | #define PRINT(fmt,...) printf(fmt, ## __VA_ARGS__) 17 | #define PRINT_LINE(fmt,...) printf(fmt" -- [%s:%d]\n", ## __VA_ARGS__, __FILE__, __LINE__) 18 | 19 | // 记录所有pid 20 | uint16 TSPacket::s_au16PIDs[E_MAX] = {PID_UNSPEC,PID_UNSPEC,PID_UNSPEC,PID_UNSPEC,PID_UNSPEC}; 21 | 22 | /***************************************************************************** 23 | * 函 数 名 : TSPacket.Parse 24 | * 函数功能 : 解析TS包 25 | * 参 数 : const uint8 *pBuf 26 | uint16 u16BufLen 27 | * 返 回 值 : TS_ERR 28 | * 作 者 : JiaSong 29 | * 创建日期 : 2015-8-29 30 | *****************************************************************************/ 31 | TS_ERR TSPacket::Parse(const uint8 *pBuf, uint16 u16BufLen) 32 | { 33 | assert(NULL != pBuf); 34 | 35 | TS_ERR ret = TS_OK; 36 | if ((NULL == pBuf) || (TS_PKT_LEN != u16BufLen)) 37 | { 38 | return TS_IN_PARAM_ERR; 39 | } 40 | 41 | if (TS_SYNC_BYTE != pBuf[0]) 42 | { 43 | return TS_SYNC_BYTE_ERR; 44 | } 45 | 46 | m_pBuf = pBuf; 47 | 48 | m_pHdr = (TSHdrFixedPart*)pBuf; 49 | m_u16PID = MK_WORD(m_pHdr->pid12_8,m_pHdr->pid7_0); 50 | m_u8CC = m_pHdr->continuity_counter; 51 | 52 | if (IsPAT()) 53 | { 54 | ret = __ParsePAT(); 55 | } 56 | else if (IsPMT()) 57 | { 58 | ret = __ParsePMT(); 59 | } 60 | else if (m_u16PID == s_au16PIDs[E_PCR]) 61 | { 62 | m_s64PCR = __GetPCR(); 63 | } 64 | 65 | if (m_pHdr->payload_unit_start_indicator) 66 | { 67 | ret = __ParsePES(); 68 | } 69 | 70 | return ret; 71 | } 72 | 73 | /***************************************************************************** 74 | * 函 数 名 : TSPacket.__HasAdaptField 75 | * 函数功能 : 判断是否存在适应区域 76 | * 参 数 : 无 77 | * 返 回 值 : bool 78 | * 作 者 : JiaSong 79 | * 创建日期 : 2015-8-29 80 | *****************************************************************************/ 81 | bool TSPacket::__HasAdaptField() 82 | { 83 | assert(NULL != m_pHdr); 84 | return 0 != (m_pHdr->adaptation_field_control & 0x2); 85 | } 86 | 87 | /***************************************************************************** 88 | * 函 数 名 : TSPacket.__HasPayload 89 | * 函数功能 : 判断是否存在负载 90 | * 参 数 : 无 91 | * 返 回 值 : bool 92 | * 作 者 : JiaSong 93 | * 创建日期 : 2015-8-29 94 | *****************************************************************************/ 95 | bool TSPacket::__HasPayload() 96 | { 97 | assert(NULL != m_pHdr); 98 | return m_pHdr->payload_unit_start_indicator || (m_pHdr->adaptation_field_control & 0x1); 99 | } 100 | 101 | /***************************************************************************** 102 | * 函 数 名 : TSPacket.__GetAdaptField 103 | * 函数功能 : 获取适应区域指针;适应区域不存在时返回NULL 104 | * 参 数 : 无 105 | * 返 回 值 : AdaptFixedPart* 106 | * 作 者 : JiaSong 107 | * 创建日期 : 2015-8-29 108 | *****************************************************************************/ 109 | AdaptFixedPart* TSPacket::__GetAdaptField() 110 | { 111 | assert(NULL != m_pBuf); 112 | assert(NULL != m_pHdr); 113 | 114 | AdaptFixedPart *pAdpt = NULL; 115 | 116 | if (__HasAdaptField()) 117 | { 118 | pAdpt = (AdaptFixedPart*)(m_pBuf + sizeof(TSHdrFixedPart)); 119 | } 120 | 121 | return pAdpt; 122 | } 123 | 124 | /***************************************************************************** 125 | * 函 数 名 : TSPacket.__GetAdaptLen 126 | * 函数功能 : 获取适应区域的长度 127 | * 参 数 : 无 128 | * 返 回 值 : uint8 129 | * 作 者 : JiaSong 130 | * 创建日期 : 2015-8-29 131 | *****************************************************************************/ 132 | uint8 TSPacket::__GetAdaptLen() 133 | { 134 | uint8 u8AdaptLen = 0; 135 | 136 | AdaptFixedPart *pAdpt = __GetAdaptField(); 137 | 138 | if (NULL != pAdpt) 139 | { 140 | // "adaptation_field_length" field is 1 byte 141 | u8AdaptLen = pAdpt->adaptation_field_length + 1; 142 | } 143 | 144 | return u8AdaptLen; 145 | } 146 | 147 | /***************************************************************************** 148 | * 函 数 名 : TSPacket.__GetPCR 149 | * 函数功能 : 存在PCR字段时,获取PCR的值;不存在时返回-1 150 | * 参 数 : 无 151 | * 返 回 值 : sint64 152 | * 作 者 : JiaSong 153 | * 创建日期 : 2015-8-29 154 | *****************************************************************************/ 155 | sint64 TSPacket::__GetPCR() 156 | { 157 | assert(NULL != m_pBuf); 158 | assert(NULL != m_pHdr); 159 | 160 | sint64 s64PCR = INVALID_VAL; 161 | if (__HasAdaptField()) 162 | { 163 | AdaptFixedPart *pAdpt = (AdaptFixedPart*)(m_pBuf + sizeof(TSHdrFixedPart)); 164 | if (pAdpt->adaptation_field_length > 0 && pAdpt->PCR_flag) 165 | { 166 | PCR *pcr = (PCR*)((const char*)pAdpt + sizeof(AdaptFixedPart)); 167 | s64PCR = MK_PCR(pcr->pcr_base32_25, 168 | pcr->pcr_base24_17, 169 | pcr->pcr_base16_9, 170 | pcr->pcr_base8_1, 171 | pcr->pcr_base0); 172 | } 173 | } 174 | return s64PCR; 175 | } 176 | 177 | /***************************************************************************** 178 | * 函 数 名 : TSPacket.__IsVideoStream 179 | * 函数功能 : 根据StreamType判断是否视频流 180 | * 参 数 : uint8 u8StreamType 181 | * 返 回 值 : bool 182 | * 作 者 : JiaSong 183 | * 创建日期 : 2015-8-29 184 | *****************************************************************************/ 185 | bool TSPacket::__IsVideoStream(uint8 u8StreamType) 186 | { 187 | return ((ES_TYPE_MPEG1V == u8StreamType) 188 | || (ES_TYPE_MPEG2V == u8StreamType) 189 | || (ES_TYPE_MPEG4V == u8StreamType) 190 | || (ES_TYPE_H264 == u8StreamType)); 191 | } 192 | 193 | /***************************************************************************** 194 | * 函 数 名 : TSPacket.__IsAudioStream 195 | * 函数功能 : 根据StreamType判断是否音频流 196 | * 参 数 : uint8 u8StreamType 197 | * 返 回 值 : bool 198 | * 作 者 : JiaSong 199 | * 创建日期 : 2015-8-29 200 | *****************************************************************************/ 201 | bool TSPacket::__IsAudioStream(uint8 u8StreamType) 202 | { 203 | return ((ES_TYPE_MPEG1A == u8StreamType) 204 | || (ES_TYPE_MPEG2A == u8StreamType) 205 | || (ES_TYPE_AC3 == u8StreamType) 206 | || (ES_TYPE_AAC == u8StreamType) 207 | || (ES_TYPE_DTS == u8StreamType)); 208 | } 209 | 210 | /***************************************************************************** 211 | * 函 数 名 : TSPacket.__GetPayloadOffset 212 | * 函数功能 : 获取负载相对于TS包头的偏移 213 | * 参 数 : 无 214 | * 返 回 值 : uint8 215 | * 作 者 : JiaSong 216 | * 创建日期 : 2015-8-29 217 | *****************************************************************************/ 218 | uint8 TSPacket::__GetPayloadOffset() 219 | { 220 | uint8 u8Pos = sizeof(TSHdrFixedPart); 221 | if (__HasAdaptField()) 222 | { 223 | u8Pos += __GetAdaptLen();; 224 | } 225 | return u8Pos; 226 | } 227 | 228 | /***************************************************************************** 229 | * 函 数 名 : TSPacket.__GetTableStartPos 230 | * 函数功能 : 获取PAT/PMT表相对于TS包头的偏移 231 | * 参 数 : 无 232 | * 返 回 值 : uint8 233 | * 作 者 : JiaSong 234 | * 创建日期 : 2015-8-29 235 | *****************************************************************************/ 236 | uint8 TSPacket::__GetTableStartPos() 237 | { 238 | assert(NULL != m_pBuf); 239 | 240 | uint8 u8Pos = __GetPayloadOffset(); 241 | if (__HasPayload()) 242 | { 243 | // "pointer_field" field is 1 byte, 244 | // and whose value is the number of bytes before payload 245 | uint8 u8PtrFieldLen = m_pBuf[u8Pos] + 1; 246 | u8Pos += u8PtrFieldLen; 247 | } 248 | return u8Pos; 249 | } 250 | 251 | /***************************************************************************** 252 | * 函 数 名 : TSPacket.__GetPTS 253 | * 函数功能 : 存在PTS字段时,获取PTS的值;不存在时返回-1 254 | * 参 数 : const OptionPESHdrFixedPart *pHdr 255 | * 返 回 值 : sint64 256 | * 作 者 : JiaSong 257 | * 创建日期 : 2015-8-29 258 | *****************************************************************************/ 259 | sint64 TSPacket::__GetPTS(const OptionPESHdrFixedPart *pHdr) 260 | { 261 | assert(NULL != pHdr); 262 | 263 | sint64 s64PTS = INVALID_VAL; 264 | if (pHdr->PTS_DTS_flags & 0x2) 265 | { 266 | PTS_DTS *pPTS = (PTS_DTS*)((char*)pHdr + sizeof(OptionPESHdrFixedPart)); 267 | s64PTS = MK_PTS_DTS(pPTS->ts32_30, pPTS->ts29_22, pPTS->ts21_15, pPTS->ts14_7, pPTS->ts6_0); 268 | } 269 | 270 | return s64PTS; 271 | } 272 | 273 | /***************************************************************************** 274 | * 函 数 名 : TSPacket.__GetDTS 275 | * 函数功能 : 存在DTS字段时,获取DTS的值;不存在时返回-1 276 | * 参 数 : const OptionPESHdrFixedPart *pHdr 277 | * 返 回 值 : sint64 278 | * 作 者 : JiaSong 279 | * 创建日期 : 2015-8-29 280 | *****************************************************************************/ 281 | sint64 TSPacket::__GetDTS(const OptionPESHdrFixedPart *pHdr) 282 | { 283 | assert(NULL != pHdr); 284 | 285 | sint64 s64DTS = INVALID_VAL; 286 | if (pHdr->PTS_DTS_flags & 0x1) 287 | { 288 | PTS_DTS *pDTS = (PTS_DTS*)((char*)pHdr + sizeof(OptionPESHdrFixedPart) + sizeof(PTS_DTS)); 289 | s64DTS = MK_PTS_DTS(pDTS->ts32_30, pDTS->ts29_22, pDTS->ts21_15, pDTS->ts14_7, pDTS->ts6_0); 290 | } 291 | 292 | return s64DTS; 293 | } 294 | 295 | /***************************************************************************** 296 | * 函 数 名 : TSPacket.__ParsePAT 297 | * 函数功能 : 解析PAT表,获取PMT信息 298 | * 参 数 : 无 299 | * 返 回 值 : TS_ERR 300 | * 作 者 : JiaSong 301 | * 创建日期 : 2015-8-29 302 | *****************************************************************************/ 303 | TS_ERR TSPacket::__ParsePAT() 304 | { 305 | assert(NULL != m_pBuf); 306 | 307 | const uint8 *pPATBuf = m_pBuf + __GetTableStartPos(); 308 | PATHdrFixedPart *pPAT = (PATHdrFixedPart*)pPATBuf; 309 | uint16 u16SectionLen = MK_WORD(pPAT->section_length11_8, pPAT->section_length7_0); 310 | uint16 u16AllSubSectionLen = u16SectionLen - (sizeof(PATHdrFixedPart) - HDR_LEN_NOT_INCLUDE) - CRC32_LEN; 311 | 312 | uint16 u16SubSectionLen = sizeof(PATSubSection); 313 | const uint8 *ptr = pPATBuf + sizeof(PATHdrFixedPart); 314 | for (uint16 i = 0; i < u16AllSubSectionLen; i+= u16SubSectionLen) 315 | { 316 | PATSubSection *pDes = (PATSubSection*)(ptr + i); 317 | uint16 u16ProgNum = pDes->program_number; 318 | uint16 u16PID = MK_WORD(pDes->pid12_8, pDes->pid7_0); 319 | if (0x00 == u16ProgNum) 320 | { 321 | uint16 u16NetworkPID = u16PID; 322 | } 323 | else 324 | { 325 | m_u16PMTPID = u16PID;// program_map_PID 326 | break; 327 | } 328 | } 329 | 330 | s_au16PIDs[E_PMT] = m_u16PMTPID; 331 | return TS_OK; 332 | } 333 | 334 | /***************************************************************************** 335 | * 函 数 名 : TSPacket.__ParsePMT 336 | * 函数功能 : 解析PMT表,获取PCR,视频和音频pid信息 337 | * 参 数 : 无 338 | * 返 回 值 : TS_ERR 339 | * 作 者 : JiaSong 340 | * 创建日期 : 2015-8-29 341 | *****************************************************************************/ 342 | TS_ERR TSPacket::__ParsePMT() 343 | { 344 | assert(NULL != m_pBuf); 345 | 346 | const uint8 *pPMTBuf = m_pBuf + __GetTableStartPos(); 347 | PMTHdrFixedPart *pPMT = (PMTHdrFixedPart*)pPMTBuf; 348 | s_au16PIDs[E_PCR] = MK_WORD(pPMT->PCR_PID12_8, pPMT->PCR_PID7_0); 349 | uint16 u16SectionLen = MK_WORD(pPMT->section_length11_8, pPMT->section_length7_0); 350 | // n * program_info_descriptor的长度 351 | uint16 u16ProgInfoLen = MK_WORD(pPMT->program_info_length11_8, pPMT->program_info_length7_0); 352 | uint16 u16AllSubSectionLen = u16SectionLen - (sizeof(PMTHdrFixedPart) - HDR_LEN_NOT_INCLUDE) - u16ProgInfoLen - CRC32_LEN; 353 | 354 | uint16 u16SubSectionLen = sizeof(PMTSubSectionFixedPart); 355 | const uint8 *ptr = pPMTBuf + sizeof(PMTHdrFixedPart) + u16ProgInfoLen; 356 | for (uint16 i = 0; i < u16AllSubSectionLen; i += u16SubSectionLen) 357 | { 358 | PMTSubSectionFixedPart *pSec = (PMTSubSectionFixedPart*)(ptr + i); 359 | uint16 u16ElementaryPID = MK_WORD(pSec->elementaryPID12_8, pSec->elementaryPID7_0); 360 | uint16 u16ESInfoLen = MK_WORD(pSec->ES_info_lengh11_8, pSec->ES_info_lengh7_0); 361 | u16SubSectionLen += u16ESInfoLen; 362 | 363 | if (__IsVideoStream(pSec->stream_type)) 364 | { 365 | s_au16PIDs[E_VIDEO] = u16ElementaryPID; 366 | } 367 | else if (__IsAudioStream(pSec->stream_type)) 368 | { 369 | s_au16PIDs[E_AUDIO] = u16ElementaryPID; 370 | } 371 | } 372 | return TS_OK; 373 | } 374 | 375 | /***************************************************************************** 376 | * 函 数 名 : TSPacket.__ParsePES 377 | * 函数功能 : 解析PES,获取PTS和DTS 378 | * 参 数 : 无 379 | * 返 回 值 : TS_ERR 380 | * 作 者 : JiaSong 381 | * 创建日期 : 2015-8-29 382 | *****************************************************************************/ 383 | TS_ERR TSPacket::__ParsePES() 384 | { 385 | assert(NULL != m_pBuf); 386 | 387 | const uint8 *pPESBuf = m_pBuf + __GetPayloadOffset(); 388 | PESHdrFixedPart *pPES = (PESHdrFixedPart*)pPESBuf; 389 | 390 | if (PES_START_CODE == pPES->packet_start_code_prefix) 391 | { 392 | m_u8StreamId = pPES->stream_id; 393 | if ((m_u8StreamId & PES_STREAM_VIDEO) || (m_u8StreamId & PES_STREAM_AUDIO)) 394 | { 395 | OptionPESHdrFixedPart *pHdr = (OptionPESHdrFixedPart*)(pPESBuf + sizeof(PESHdrFixedPart)); 396 | m_s64PTS = __GetPTS(pHdr); 397 | m_s64DTS = __GetDTS(pHdr); 398 | } 399 | } 400 | return TS_OK; 401 | } 402 | 403 | TSParser::TSParser(const char *pFilePath) : m_strFile(""), m_pFd(NULL) 404 | { 405 | m_strFile = pFilePath; 406 | } 407 | TSParser::~TSParser() 408 | { 409 | __CloseFile(); 410 | } 411 | 412 | /***************************************************************************** 413 | * 函 数 名 : TSParser.Parse 414 | * 函数功能 : 解析TS文件 415 | * 参 数 : 无 416 | * 返 回 值 : TS_ERR 417 | * 作 者 : JiaSong 418 | * 创建日期 : 2015-8-29 419 | *****************************************************************************/ 420 | TS_ERR TSParser::Parse() 421 | { 422 | TS_ERR ret = TS_OK; 423 | ret = __OpenFile(); 424 | RETURN_IF_NOT_OK(ret); 425 | 426 | if (!__SeekToFirstPkt()) 427 | { 428 | PRINT_LINE("Seek to first packet failed!"); 429 | return TS_FILE_SEEK_FAIL; 430 | } 431 | 432 | sint64 s64CurPos = ftello64(m_pFd); 433 | PRINT_LINE("Seek to first packet, offset: 0x%08llX", s64CurPos); 434 | 435 | uint32 u32ReadBufLen = MAX_READ_PKT_NUM * TS_PKT_LEN; 436 | uint8 *pReadBuf = new uint8[u32ReadBufLen]; 437 | AutoDelCharBuf tBuf(pReadBuf); 438 | uint32 u32PktNo = 0; 439 | while (0 == feof(m_pFd)) 440 | { 441 | sint32 s32ReadLen = fread(pReadBuf, 1, u32ReadBufLen, m_pFd); 442 | if (s32ReadLen >= 0) 443 | { 444 | uint32 u32Count = s32ReadLen / TS_PKT_LEN; 445 | for (uint32 i = 0; i < u32Count; i++) 446 | { 447 | if (TS_SYNC_BYTE == pReadBuf[i*TS_PKT_LEN]) 448 | { 449 | TSPacket tPkt; 450 | ret = tPkt.Parse(pReadBuf + i*TS_PKT_LEN, TS_PKT_LEN); 451 | RETURN_IF_NOT_OK(ret); 452 | 453 | __PrintPacketInfo(tPkt, s64CurPos, u32PktNo); 454 | s64CurPos += TS_PKT_LEN; 455 | u32PktNo++; 456 | } 457 | else 458 | { 459 | PRINT_LINE("###### PktNo: %08d, Offset: 0x%08X, Sync byte error! First byte<0x%02X>", 460 | u32PktNo, s64CurPos, pReadBuf[i*TS_PKT_LEN]); 461 | if (!__SeekToFirstPkt(s64CurPos)) 462 | { 463 | PRINT_LINE("###### Seek to next packet failed!"); 464 | return TS_FILE_SEEK_FAIL; 465 | } 466 | s64CurPos = ftello64(m_pFd); 467 | break; 468 | } 469 | } 470 | } 471 | else 472 | { 473 | PRINT_LINE("###### Read file error, ret<%d>", s32ReadLen); 474 | break; 475 | } 476 | } 477 | 478 | PRINT_LINE("Parse file complete!"); 479 | return ret; 480 | } 481 | 482 | /***************************************************************************** 483 | * 函 数 名 : TSParser.__OpenFile 484 | * 函数功能 : 打开TS文件 485 | * 参 数 : 无 486 | * 返 回 值 : TS_ERR 487 | * 作 者 : JiaSong 488 | * 创建日期 : 2015-8-29 489 | *****************************************************************************/ 490 | TS_ERR TSParser::__OpenFile() 491 | { 492 | m_pFd = fopen(m_strFile.c_str(), "rb"); 493 | if (NULL == m_pFd) 494 | { 495 | PRINT_LINE("###### Open file<%s> failed! errno<%d>", m_strFile.c_str(), errno); 496 | return TS_FILE_OPEN_FAIL; 497 | } 498 | 499 | PRINT_LINE("Open file<%s> success.", m_strFile.c_str()); 500 | return TS_OK; 501 | } 502 | 503 | /***************************************************************************** 504 | * 函 数 名 : TSParser.__CloseFile 505 | * 函数功能 : 关闭文件 506 | * 参 数 : 无 507 | * 返 回 值 : TS_ERR 508 | * 作 者 : JiaSong 509 | * 创建日期 : 2015-8-29 510 | *****************************************************************************/ 511 | TS_ERR TSParser::__CloseFile() 512 | { 513 | if (NULL != m_pFd) 514 | { 515 | fclose(m_pFd); 516 | m_pFd = NULL; 517 | PRINT_LINE("Close file<%s>", m_strFile.c_str()); 518 | } 519 | return TS_OK; 520 | } 521 | 522 | /***************************************************************************** 523 | * 函 数 名 : TSParser.__SeekToFirstPkt 524 | * 函数功能 : 将文件读取指针偏移至第一个合法的TS包 525 | * 参 数 : uint64 u64Offset 526 | * 返 回 值 : bool 527 | * 作 者 : JiaSong 528 | * 创建日期 : 2015-8-29 529 | *****************************************************************************/ 530 | bool TSParser::__SeekToFirstPkt(uint64 u64Offset) 531 | { 532 | fseek(m_pFd, u64Offset, SEEK_SET); 533 | 534 | uint32 u32ReadBufLen = MAX_READ_PKT_NUM * TS_PKT_LEN; 535 | uint8 *pReadBuf = new uint8[u32ReadBufLen]; 536 | AutoDelCharBuf tBuf(pReadBuf); 537 | sint32 s32ReadLen = fread(pReadBuf, 1, u32ReadBufLen, m_pFd); 538 | if (s32ReadLen > 0) 539 | { 540 | uint32 u32PktCount = s32ReadLen / TS_PKT_LEN; 541 | uint32 u32Count = MIN(MAX_CHECK_PKT_NUM, u32PktCount); 542 | for (uint32 i = 0; i < s32ReadLen - u32Count*TS_PKT_LEN; i++) 543 | { 544 | if (TS_SYNC_BYTE == pReadBuf[i]) 545 | { 546 | uint32 n = 0; 547 | for (; n < u32Count; n++) 548 | { 549 | if (TS_SYNC_BYTE != pReadBuf[i + n*TS_PKT_LEN]) 550 | { 551 | break; 552 | } 553 | } 554 | 555 | if (u32Count == n) 556 | { 557 | return (0 == fseek(m_pFd, u64Offset+i, SEEK_SET)); 558 | } 559 | } 560 | } 561 | } 562 | else 563 | { 564 | PRINT_LINE("###### Read file error, ret<%d>", s32ReadLen); 565 | } 566 | 567 | return false; 568 | } 569 | 570 | /***************************************************************************** 571 | * 函 数 名 : TSParser.__PrintPacketInfo 572 | * 函数功能 : 打印TS包的信息 573 | * 参 数 : TSPacket &tPkt 574 | uint64 u64Offset 575 | uint32 u32PktNo 576 | * 返 回 值 : void 577 | * 作 者 : JiaSong 578 | * 创建日期 : 2015-8-29 579 | *****************************************************************************/ 580 | void TSParser::__PrintPacketInfo(TSPacket &tPkt, uint64 u64Offset, uint32 u32PktNo) 581 | { 582 | PRINT("PktNo: %08u, Offset: 0x%08llX, PID: 0x%04X, CC: %02u", 583 | u32PktNo, u64Offset, tPkt.GetPID(), tPkt.GetCC()); 584 | 585 | if (tPkt.IsPAT()) 586 | { 587 | PRINT(", PAT"); 588 | } 589 | else if (tPkt.IsPMT()) 590 | { 591 | PRINT(", PMT"); 592 | } 593 | else if (tPkt.GetPCR() >= 0) 594 | { 595 | PRINT(", PCR: %lld(%s)", tPkt.GetPCR(), __TSTimeToStr(tPkt.GetPCR())); 596 | } 597 | else if (PID_NULL == tPkt.GetPID()) 598 | { 599 | PRINT(", Null Packet"); 600 | } 601 | 602 | if (tPkt.GetPTS() >= 0) 603 | { 604 | PRINT(", PTS: %lld(%s)", tPkt.GetPTS(), __TSTimeToStr(tPkt.GetPTS())); 605 | } 606 | if (tPkt.GetDTS() >= 0) 607 | { 608 | PRINT(", DTS: %lld(%s)", tPkt.GetDTS(), __TSTimeToStr(tPkt.GetDTS())); 609 | } 610 | 611 | if (tPkt.IsVideo()) 612 | { 613 | PRINT(", Video"); 614 | } 615 | else if (tPkt.IsAudio()) 616 | { 617 | PRINT(", Audio"); 618 | } 619 | 620 | PRINT_LINE(""); 621 | } 622 | 623 | /***************************************************************************** 624 | * 函 数 名 : TSParser.__PrintPacketInfo 625 | * 函数功能 : TS时戳转化成可读时间字符串 626 | * 参 数 : sint64 s64Time 627 | * 返 回 值 : const char * 628 | * 作 者 : JiaSong 629 | * 创建日期 : 2016-4-11 630 | *****************************************************************************/ 631 | const char *TSParser::__TSTimeToStr(sint64 s64Time) 632 | { 633 | static char s_acTimeStr[MAX_TIME_STR_LEN] = {0}; 634 | sint64 s64MiliSecond = s64Time / 90; 635 | sint64 s64Second = s64MiliSecond / 1000; 636 | snprintf(s_acTimeStr, sizeof(s_acTimeStr), "%02d:%02d:%02d.%03d", 637 | s64Second/3600, (s64Second%3600)/60, s64Second%60, s64MiliSecond%1000); 638 | return s_acTimeStr; 639 | } 640 | 641 | -------------------------------------------------------------------------------- /TSParser.h: -------------------------------------------------------------------------------- 1 | #ifndef __TS_PARSER_H__ 2 | #define __TS_PARSER_H__ 3 | 4 | #include "types.h" 5 | #include 6 | using namespace std; 7 | 8 | typedef enum TS_ERR 9 | { 10 | TS_OK = 0, 11 | TS_IN_PARAM_ERR, 12 | TS_SYNC_BYTE_ERR, 13 | TS_FILE_OPEN_FAIL, 14 | TS_FILE_SEEK_FAIL, 15 | }TS_ERR; 16 | 17 | // PID种类 18 | typedef enum E_PKT_TYPE 19 | { 20 | E_PAT = 0, 21 | E_PMT = 1, 22 | E_PCR = 2, 23 | E_AUDIO = 3, 24 | E_VIDEO = 4, 25 | E_MAX = 5 26 | }E_PKT_TYPE; 27 | 28 | class TSPacket 29 | { 30 | public: 31 | TSPacket() 32 | : m_pBuf(NULL) 33 | , m_pHdr(NULL) 34 | , m_u16PID(PID_UNSPEC) 35 | , m_u8CC(0) 36 | , m_u16PMTPID(PID_UNSPEC) 37 | , m_u8StreamId(0) 38 | , m_s64PCR(INVALID_VAL) 39 | , m_s64PTS(INVALID_VAL) 40 | , m_s64DTS(INVALID_VAL) 41 | {} 42 | ~TSPacket() {} 43 | 44 | TS_ERR Parse(const uint8 *pBuf, uint16 u16BufLen); 45 | 46 | uint16 GetPID() const { return m_u16PID; } 47 | uint8 GetCC() const { return m_u8CC; } 48 | 49 | bool IsPAT() { return (PID_PAT == m_u16PID); } 50 | uint16 GetPMTPID() const { return m_u16PMTPID; } 51 | 52 | bool IsPMT() { return (PID_UNSPEC != m_u16PID) && (s_au16PIDs[E_PMT] == m_u16PID); } 53 | bool IsVideo() { return (s_au16PIDs[E_VIDEO] == m_u16PID); } 54 | bool IsAudio() { return (s_au16PIDs[E_AUDIO] == m_u16PID); } 55 | 56 | sint64 GetPCR() const { return m_s64PCR; } 57 | sint64 GetPTS() const { return m_s64PTS; } 58 | sint64 GetDTS() const { return m_s64DTS; } 59 | 60 | public: 61 | static uint16 s_au16PIDs[E_MAX]; // 记录所有pid 62 | 63 | private: 64 | bool __HasAdaptField(); 65 | bool __HasPayload(); 66 | AdaptFixedPart* __GetAdaptField(); 67 | uint8 __GetAdaptLen(); 68 | sint64 __GetPCR(); 69 | bool __IsVideoStream(uint8 u8StreamType); 70 | bool __IsAudioStream(uint8 u8StreamType); 71 | uint8 __GetPayloadOffset(); 72 | uint8 __GetTableStartPos(); 73 | sint64 __GetPTS(const OptionPESHdrFixedPart *pHdr); 74 | sint64 __GetDTS(const OptionPESHdrFixedPart *pHdr); 75 | TS_ERR __ParsePAT(); 76 | TS_ERR __ParsePMT(); 77 | TS_ERR __ParsePES(); 78 | 79 | private: 80 | const uint8 *m_pBuf; 81 | TSHdrFixedPart *m_pHdr; 82 | uint16 m_u16PID; 83 | uint8 m_u8CC; 84 | uint16 m_u16PMTPID; 85 | uint8 m_u8StreamId; 86 | sint64 m_s64PCR; 87 | sint64 m_s64PTS; 88 | sint64 m_s64DTS; 89 | }; 90 | 91 | class TSParser 92 | { 93 | public: 94 | TSParser(const char *pFilePath); 95 | ~TSParser(); 96 | 97 | TS_ERR Parse(); 98 | 99 | private: 100 | TS_ERR __OpenFile(); 101 | TS_ERR __CloseFile(); 102 | bool __SeekToFirstPkt(uint64 u64Offset=0); 103 | void __PrintPacketInfo(TSPacket &tPkt, uint64 u64Offset, uint32 u32PktNo); 104 | const char *__TSTimeToStr(sint64 s64Time); 105 | 106 | private: 107 | string m_strFile; 108 | FILE* m_pFd; 109 | }; 110 | 111 | #define DELETER_BUFFER(p) if (NULL != p) { delete p; p = NULL;} 112 | 113 | class AutoDelCharBuf 114 | { 115 | public: 116 | AutoDelCharBuf(uint8 *pBuf) : m_pBuf(pBuf) {} 117 | ~AutoDelCharBuf() { DELETER_BUFFER(m_pBuf); } 118 | 119 | uint8 *Ptr() { return m_pBuf; } 120 | private: 121 | uint8 *m_pBuf; 122 | }; 123 | 124 | #endif //__TS_PARSER_H__ 125 | 126 | -------------------------------------------------------------------------------- /demo.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2854/TSParser/1ee4d0e9329704e0aab117183bd4627af0e7e09a/demo.ts -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "TSParser.h" 3 | 4 | void PrintUsage(const char *pAppPath) 5 | { 6 | printf("Usage: %s file\n", pAppPath); 7 | printf("Demo : %s /home/demo.ts\n", pAppPath); 8 | } 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | if (argc < 2) 13 | { 14 | PrintUsage(argv[0]); 15 | exit(0); 16 | } 17 | 18 | TSParser tParser(argv[1]); 19 | tParser.Parse(); 20 | 21 | return 0; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | TARGET := tsparser 2 | 3 | CC := gcc 4 | CFLAGS := -Wall -O2 -g 5 | LDFLAGS+= -lstdc++ 6 | SOURCE := $(wildcard *.cpp) 7 | OBJS := $(patsubst %.cpp, %.o, $(SOURCE)) 8 | 9 | all: $(TARGET) 10 | $(TARGET) : $(OBJS) 11 | @$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET) 12 | 13 | .PHONY: clean 14 | 15 | clean: 16 | @rm -f $(TARGET) $(OBJS) *.o 17 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | #ifndef __TS_TYPES__ 2 | #define __TS_TYPES__ 3 | 4 | #include 5 | #include 6 | 7 | typedef unsigned char uint8; 8 | typedef unsigned short uint16; 9 | typedef unsigned int uint32; 10 | 11 | typedef signed char sint8; 12 | typedef signed short sint16; 13 | typedef signed int sint32; 14 | 15 | #ifdef _WIN32 16 | typedef unsigned __int64 uint64; 17 | typedef signed __int64 uint64; 18 | #else 19 | typedef unsigned long long uint64; 20 | typedef signed long long sint64; 21 | #endif 22 | 23 | #define true 1 24 | #define false 0 25 | 26 | #define INVALID_VAL -1 27 | 28 | #define TS_PKT_LEN 188 29 | #define TS_SYNC_BYTE 0x47 30 | #define STUFFING_BYTE 0xFF 31 | #define PES_START_CODE 0x010000 // PES分组起始标志0x000001 32 | #define CRC32_LEN 4 33 | #define HDR_LEN_NOT_INCLUDE 3 // PAT/PMT中包含section length字段的头长度 34 | 35 | #define PID_PAT 0x0000 36 | #define PID_CAT 0x0001 37 | #define PID_TSDT 0x0002 38 | #define PID_DVB_NIT 0x0010 39 | #define PID_DVB_SDT 0x0011 40 | #define PID_DVB_EIT 0x0012 41 | #define PID_DVB_RST 0x0013 42 | #define PID_DVB_TDT 0x0014 43 | #define PID_DVB_SYNC 0x0015 44 | #define PID_DVB_INBAND 0x001c 45 | #define PID_DVB_MEASUREMENT 0x001d 46 | #define PID_DVB_DIT 0x001e 47 | #define PID_DVB_SIT 0x001f 48 | #define PID_NULL 0x1fff 49 | #define PID_UNSPEC 0xffff 50 | 51 | #define PES_STREAM_VIDEO 0xE0 52 | #define PES_STREAM_AUDIO 0xC0 53 | 54 | #define ES_TYPE_MPEG1V 0x01 55 | #define ES_TYPE_MPEG2V 0x02 56 | #define ES_TYPE_MPEG1A 0x03 57 | #define ES_TYPE_MPEG2A 0x04 58 | #define ES_TYPE_PRIVATESECTS 0x05 59 | #define ES_TYPE_PRIVATEDATA 0x06 60 | #define ES_TYPE_MHEG 0x07 61 | #define ES_TYPE_DSMCC 0x08 62 | #define ES_TYPE_AUXILIARY 0x09 63 | #define ES_TYPE_DSMCC_ENCAP 0x0a 64 | #define ES_TYPE_DSMCC_UN 0x0b 65 | #define ES_TYPE_AAC 0x0f 66 | #define ES_TYPE_MPEG4V 0x10 67 | #define ES_TYPE_LATM_AAC 0x11 68 | #define ES_TYPE_MPEG4_GENERIC 0x12 69 | /* Unknown 0x13 */ 70 | #define ES_TYPE_DSMCC_DOWNLOAD 0x14 71 | /* Unknown 0x15 */ 72 | /* Unknown 0x16 */ 73 | /* Unknown 0x17 */ 74 | /* Unknown 0x1a */ 75 | #define ES_TYPE_H264 0x1b 76 | #define ES_TYPE_DIGICIPHER2V 0x80 77 | #define ES_TYPE_AC3 0x81 78 | #define ES_TYPE_DCA 0x82 79 | #define ES_TYPE_LPCM 0x83 80 | #define ES_TYPE_SDDS 0x84 81 | #define ES_TYPE_ATSC_PROGID 0x85 82 | #define ES_TYPE_DTSHD 0x86 83 | #define ES_TYPE_EAC3 0x87 84 | #define ES_TYPE_DTS 0x8a 85 | #define ES_TYPE_DVB_SLICE 0x90 86 | #define ES_TYPE_AC3B 0x91 87 | #define ES_TYPE_SUBTITLE 0x92 88 | #define ES_TYPE_SDDSB 0x94 89 | #define ES_TYPE_MSCODEC 0xa0 90 | #define ES_TYPE_DIRAC 0xd1 91 | #define ES_TYPE_VC1 0xea 92 | 93 | #define TID_PAT 0x00 94 | #define TID_CAT 0x01 95 | #define TID_PMT 0x02 96 | #define TID_DVB_NIT 0x40 97 | #define TID_DVB_ONIT 0x41 98 | 99 | #define DESC_VIDEO 0x02 100 | #define DESC_AUDIO 0x03 101 | #define DESC_HIERARCHY 0x04 102 | #define DESC_REGISTRATION 0x05 103 | #define DESC_DSA 0x06 /* data stream alignment */ 104 | #define DESC_TBG 0x07 /* target background grid */ 105 | #define DESC_VIDEOWINDOW 0x08 106 | #define DESC_CA 0x09 107 | #define DESC_LANGUAGE 0x0a 108 | #define DESC_CLOCK 0x0b 109 | #define DESC_MBU 0x0c /* multiplex buffer utilisation */ 110 | #define DESC_COPYRIGHT 0x0d 111 | #define DESC_MAXBITRATE 0x0e 112 | 113 | #define PT_UNSPEC 0 114 | #define PT_SECTIONS 1 115 | #define PT_PES 2 116 | #define PT_DATA 3 117 | #define PT_NULL 4 118 | 119 | #define PST_UNSPEC 0 120 | #define PST_VIDEO 1 121 | #define PST_AUDIO 2 122 | #define PST_INTERACTIVE 3 123 | #define PST_CC 4 124 | #define PST_IP 5 125 | #define PST_SI 6 126 | #define PST_NI 7 127 | 128 | #ifdef BIG_ENDIAN 129 | #undef BIG_ENDIAN 130 | #endif 131 | 132 | #pragma pack(push, 1) // 1字节对齐 133 | typedef struct TSHdrFixedPart 134 | { 135 | uint8 sync_byte:8; 136 | #ifdef BIG_ENDIAN 137 | uint8 transport_error_indicator:1; 138 | uint8 payload_unit_start_indicator:1; 139 | uint8 transport_priority:1; 140 | uint8 pid12_8:5; 141 | uint8 pid7_0:8; 142 | uint8 transport_scrambling_control:2; 143 | uint8 adaptation_field_control:2; 144 | uint8 continuity_counter:4; 145 | #else // LITTLE_ENDIAN 146 | uint8 pid12_8:5; 147 | uint8 transport_priority:1; 148 | uint8 payload_unit_start_indicator:1; 149 | uint8 transport_error_indicator:1; 150 | uint8 pid7_0:8; 151 | uint8 continuity_counter:4; 152 | uint8 adaptation_field_control:2; 153 | uint8 transport_scrambling_control:2; 154 | #endif 155 | }TSHdrFixedPart; 156 | 157 | typedef struct AdaptFixedPart 158 | { 159 | uint8 adaptation_field_length:8; 160 | #ifdef BIG_ENDIAN 161 | uint8 discontinuity_indicator:1; 162 | uint8 random_access_indicator:1; 163 | uint8 elementary_stream_priority_indicator:1; 164 | uint8 PCR_flag:1; 165 | uint8 OPCR_flag:1; 166 | uint8 splicing_point_flag:1; 167 | uint8 transport_private_data_flag:1; 168 | uint8 adaptation_field_extension_flag:1; 169 | #else // LITTLE_ENDIAN 170 | uint8 adaptation_field_extension_flag:1; 171 | uint8 transport_private_data_flag:1; 172 | uint8 splicing_point_flag:1; 173 | uint8 OPCR_flag:1; 174 | uint8 PCR_flag:1; 175 | uint8 elementary_stream_priority_indicator:1; 176 | uint8 random_access_indicator:1; 177 | uint8 discontinuity_indicator:1; 178 | #endif 179 | }AdaptFixedPart; 180 | 181 | typedef struct PCR 182 | { 183 | uint8 pcr_base32_25:8; 184 | uint8 pcr_base24_17:8; 185 | uint8 pcr_base16_9:8; 186 | uint8 pcr_base8_1:8; 187 | #ifdef BIG_ENDIAN 188 | uint8 pcr_base0:1; 189 | uint8 reserved:6; 190 | uint8 pcr_extension8:1; 191 | #else // LITTLE_ENDIAN 192 | uint8 pcr_extension8:1; 193 | uint8 reserved:6; 194 | uint8 pcr_base0:1; 195 | #endif 196 | uint8 pcr_extension7_0:8; 197 | }PCR; 198 | 199 | typedef struct PESHdrFixedPart 200 | { 201 | uint32 packet_start_code_prefix:24; 202 | uint8 stream_id:8; 203 | uint16 PES_packet_length:16; 204 | }PESHdrFixedPart; 205 | 206 | typedef struct OptionPESHdrFixedPart 207 | { 208 | #ifdef BIG_ENDIAN 209 | uint8 fix_2bits:2; // "10" 210 | uint8 PES_scrambling_control:2; // "00" Not scramble; "01","10","11" User-defined 211 | uint8 PES_priority:1; 212 | uint8 data_alignment_indicator:1; 213 | uint8 copyright:1; 214 | uint8 original_or_copy:1; 215 | 216 | uint8 PTS_DTS_flags:2; 217 | uint8 ESCR_flag:1; 218 | uint8 ES_rate_flag:1; 219 | uint8 DSM_trick_mode_flag:1; 220 | uint8 additional_copy_info_flag:1; 221 | uint8 PES_CRC_flag:1; 222 | uint8 PES_extension_flag:1; 223 | #else // LITTLE_ENDIAN 224 | uint8 original_or_copy:1; 225 | uint8 copyright:1; 226 | uint8 data_alignment_indicator:1; 227 | uint8 PES_priority:1; 228 | uint8 PES_scrambling_control:2; 229 | uint8 fix_10:2; 230 | 231 | uint8 PES_extension_flag:1; 232 | uint8 PES_CRC_flag:1; 233 | uint8 additional_copy_info_flag:1; 234 | uint8 DSM_trick_mode_flag:1; 235 | uint8 ES_rate_flag:1; 236 | uint8 ESCR_flag:1; 237 | uint8 PTS_DTS_flags:2; 238 | #endif 239 | uint8 PES_Hdr_data_length:8; 240 | }OptionPESHdrFixedPart; 241 | 242 | typedef struct PTS_DTS 243 | { 244 | #ifdef BIG_ENDIAN 245 | uint8 fix_4bits:4; // PTS is "0010" or "0011", DTS is "0001" 246 | uint8 ts32_30:3; 247 | uint8 marker_bit1:1; 248 | uint8 ts29_22:8; 249 | uint8 ts21_15:7; 250 | uint8 marker_bit2:1; 251 | uint8 ts14_7:8; 252 | uint8 ts6_0:7; 253 | uint8 marker_bit3:1; 254 | #else // LITTLE_ENDIAN 255 | uint8 marker_bit1:1; 256 | uint8 ts32_30:3; 257 | uint8 fix_4bits:4; // PTS is "0010" or "0011", DTS is "0001" 258 | uint8 ts29_22:8; 259 | uint8 marker_bit2:1; 260 | uint8 ts21_15:7; 261 | uint8 ts14_7:8; 262 | uint8 marker_bit3:1; 263 | uint8 ts6_0:7; 264 | #endif 265 | }PTS_DTS; 266 | 267 | typedef struct PATHdrFixedPart 268 | { 269 | uint8 table_id:8; 270 | #ifdef BIG_ENDIAN 271 | uint8 section_syntax_indicator:1; 272 | uint8 zero_bit:1; // '0' 273 | uint8 reserved1:2; 274 | uint8 section_length11_8:4; 275 | uint8 section_length7_0:8; 276 | uint16 transport_stream_id:16; 277 | uint8 reserved2:2; 278 | uint8 version_number:5; 279 | uint8 current_next_indicator:1; 280 | #else // LITTLE_ENDIAN 281 | uint8 section_length11_8:4; 282 | uint8 reserved1:2; 283 | uint8 zero_bit:1; // '0' 284 | uint8 section_syntax_indicator:1; 285 | uint8 section_length7_0:8; 286 | uint16 transport_stream_id:16; 287 | uint8 current_next_indicator:1; 288 | uint8 version_number:5; 289 | uint8 reserved2:2; 290 | #endif 291 | uint8 section_number:8; 292 | uint8 last_section_number:8; 293 | }PATHdrFixedPart; 294 | 295 | typedef struct PATSubSection 296 | { 297 | uint16 program_number:16; 298 | #ifdef BIG_ENDIAN 299 | uint8 reserved:3; 300 | uint8 pid12_8:5; 301 | #else // LITTLE_ENDIAN 302 | uint8 pid12_8:5; 303 | uint8 reserved:3; 304 | #endif 305 | uint8 pid7_0:8; 306 | }PATSubSection; 307 | 308 | typedef struct CATHdrFixedPart 309 | { 310 | uint8 table_id:8; 311 | #ifdef BIG_ENDIAN 312 | uint8 section_syntax_indicator:1; 313 | uint8 zero_bit:1; // '0' 314 | uint8 reserved1:2; 315 | uint8 section_length11_8:4; 316 | uint8 section_length7_0:8; 317 | uint16 reserved2:16; 318 | uint8 reserved3:2; 319 | uint8 version_number:5; 320 | uint8 current_next_indicator:1; 321 | #else // LITTLE_ENDIAN 322 | uint8 section_length11_8:4; 323 | uint8 reserved1:2; 324 | uint8 zero_bit:1; // '0' 325 | uint8 section_syntax_indicator:1; 326 | uint8 section_length7_0:8; 327 | uint16 reserved2:16; 328 | uint8 current_next_indicator:1; 329 | uint8 version_number:5; 330 | uint8 reserved3:2; 331 | #endif 332 | uint8 section_number:8; 333 | uint8 last_section_number:8; 334 | }CATHdrFixedPart; 335 | 336 | typedef struct PMTHdrFixedPart 337 | { 338 | uint8 table_id:8; 339 | #ifdef BIG_ENDIAN 340 | uint8 section_syntax_indicator:1; 341 | uint8 zero_bit:1; // '0' 342 | uint8 reserved1:2; 343 | uint8 section_length11_8:4; 344 | uint8 section_length7_0:8; 345 | uint16 program_number:16; 346 | uint8 reserved2:2; 347 | uint8 version_number:5; 348 | uint8 current_next_indicator:1; 349 | uint8 section_number:8; 350 | uint8 last_section_number:8; 351 | uint8 reserved3:3; 352 | uint8 PCR_PID12_8:5; 353 | uint8 PCR_PID7_0:8; 354 | uint8 reserved4:4; 355 | uint8 program_info_length11_8:4; 356 | uint8 program_info_length7_0:8; 357 | #else // LITTLE_ENDIAN 358 | uint8 section_length11_8:4; 359 | uint8 reserved1:2; 360 | uint8 zero_bit:1; // '0' 361 | uint8 section_syntax_indicator:1; 362 | uint8 section_length7_0:8; 363 | uint16 transport_stream_id:16; 364 | uint8 current_next_indicator:1; 365 | uint8 version_number:5; 366 | uint8 reserved2:2; 367 | uint8 section_number:8; 368 | uint8 last_section_number:8; 369 | uint8 PCR_PID12_8:5; 370 | uint8 reserved3:3; 371 | uint8 PCR_PID7_0:8; 372 | uint8 program_info_length11_8:4; 373 | uint8 reserved4:4; 374 | uint8 program_info_length7_0:8; 375 | #endif 376 | }PMTHdrFixedPart; 377 | 378 | typedef struct PMTSubSectionFixedPart 379 | { 380 | uint8 stream_type:8; 381 | #ifdef BIG_ENDIAN 382 | uint8 reserved1:3; 383 | uint8 elementaryPID12_8:5; 384 | uint8 elementaryPID7_0:8; 385 | uint8 reserved2:4; 386 | uint8 ES_info_lengh11_8:4; 387 | uint8 ES_info_lengh7_0:8; 388 | #else // LITTLE_ENDIAN 389 | uint8 elementaryPID12_8:5; 390 | uint8 reserved1:3; 391 | uint8 elementaryPID7_0:8; 392 | uint8 ES_info_lengh11_8:4; 393 | uint8 reserved2:4; 394 | uint8 ES_info_lengh7_0:8; 395 | #endif 396 | }PMTSubSectionFixedPart; 397 | #pragma pack(pop) //恢复对齐状态 398 | 399 | #endif //__TS_TYPES__ 400 | 401 | --------------------------------------------------------------------------------