TS格式解析
1.TS格式介紹
?? TS:全稱為MPEG2-TS。TS即"Transport Stream"的縮寫。它是分包發(fā)送的,每一個(gè)包長為188字節(jié)(還有192和204個(gè)字節(jié)的包)。包的結(jié)構(gòu)為,包頭為4個(gè)字節(jié)(第一個(gè)字節(jié)為0x47),負(fù)載為184個(gè)字節(jié)。在TS流里可以填入很多類型的數(shù)據(jù),如視頻、音頻、自定義信息等。MPEG2-TS主要應(yīng)用于實(shí)時(shí)傳送的節(jié)目,比如實(shí)時(shí)廣播的電視節(jié)目。MPEG2-TS格式的特點(diǎn)就是要求從視頻流的任一片段開始都是可以獨(dú)立解碼的。簡單地說,將DVD上的VOB文件的前面一截cut掉(或者是數(shù)據(jù)損壞數(shù)據(jù))就會(huì)導(dǎo)致整個(gè)文件無法解碼,而電視節(jié)目是任何時(shí)候打開電視機(jī)都能解碼(收看)的。
?? TS解析需要參考:ISO/IEC 13818-1的2.4 Transport Stream bitstream requirements
2.TS流包含的內(nèi)容
? ??一段TS流,必須包含PAT包、PMT包、多個(gè)音頻包、多個(gè)視頻包、多個(gè)PCR包、以及其他信息包。
? ??解析TS流數(shù)據(jù)的流程:查找PID為0x0的包,解析PAT,PAT包中的program_map_PID表示PMT的PID;查找PMT,PMT包中的elementary_PID表示音視頻包的PID,PMT包中的PCR_PID表示PCR的PID,有的時(shí)候PCR的PID跟音頻或者視頻的PID相同,說明PCR會(huì)融進(jìn)音視頻的包,注意解析,有的時(shí)候PCR是自己單獨(dú)的包;CAT、NIT、SDT、EIT的PID分別為: 0x01、0x10、0x11、0x12。
3.TS包頭解析
??? TS包頭有4個(gè)字節(jié)
| //Transport Stream header typedef?struct?TS_header { ?????????unsigned sync_byte??????????????????? :8;????? //同步字節(jié),固定為0x47 ,表示后面的是一個(gè)TS分組,當(dāng)然,后面包中的數(shù)據(jù)是不會(huì)出現(xiàn)0x47的 ?????????unsigned transport_error_indicator?????? :1;????? //傳輸錯(cuò)誤標(biāo)志位,一般傳輸錯(cuò)誤的話就不會(huì)處理這個(gè)包了 ?????????unsigned payload_unit_start_indicator??? :1;????? //有效負(fù)載的開始標(biāo)志,根據(jù)后面有效負(fù)載的內(nèi)容不同功能也不同 ?????????// payload_unit_start_indicator為1時(shí),在前4個(gè)字節(jié)之后會(huì)有一個(gè)調(diào)整字節(jié),它的數(shù)值決定了負(fù)載內(nèi)容的具體開始位置。 ?????????unsigned transport_priority????????????? :1;????? //傳輸優(yōu)先級(jí)位,1表示高優(yōu)先級(jí) ?????????unsigned PID????????????????????????? :13;???? //有效負(fù)載數(shù)據(jù)的類型 ?????????unsigned transport_scrambling_control???? :2;????? //加密標(biāo)志位,00表示未加密 ?????????unsigned adaption_field_control????????? :2;????? //調(diào)整字段控制,。01僅含有效負(fù)載,10僅含調(diào)整字段,11含有調(diào)整字段和有效負(fù)載。為00的話解碼器不進(jìn)行處理。 ?????????unsigned continuity_counter????????????? :4;????? //一個(gè)4bit的計(jì)數(shù)器,范圍0-15 } TS_header; ????//特殊參數(shù)說明: ???//sync_byte:0x47 ???//payload_unit_start_indicator:0x01表示含有PSI或者PES頭 ???//PID:0x0表示后面負(fù)載內(nèi)容為PAT,不同的PID表示不同的負(fù)載 ???//adaption_field_control: ????????// 0x0: // reserved for future use by ISO/IEC ????????// 0x1: // 無調(diào)整字段,僅含有效負(fù)載?? ????????// 0x2: // 僅含調(diào)整字段,無有效負(fù)載 ????????// 0x3: // 調(diào)整字段后含有效負(fù)載 // Parse TS header int?Parse_TS_header(unsignedchar?*pTSBuf, TS_header *pheader) { ????pheader->sync_byte???????????????????????????????????? = pTSBuf[0]; ????if?(pheader->sync_byte != 0x47) ????????return?-1; ????pheader->transport_error_indicator?????? = pTSBuf[1] >> 7; ????pheader->payload_unit_start_indicator??? = pTSBuf[1] >> 6 & 0x01; ????pheader->transport_priority???????????? = pTSBuf[1] >> 5 & 0x01; ????pheader->PID???????????????????????? = (pTSBuf[1] & 0x1F) << 8 | pTSBuf[2]; ????pheader->transport_scrambling_control?? = pTSBuf[3] >> 6; ????pheader->adaption_field_control???????? = pTSBuf[3] >> 4 & 0x03; ????pheader->continuity_counter??????????? = pTSBuf[3] & 0x0F; ????return?0; } |
????? TS包頭解析需要參考:ISO/IEC 13818-1的2.4.3.2 Transport Stream packet layer
4.TS負(fù)載格式解析
4.1 PAT解析
?? TS_header包頭中的PID值為0x0,表示當(dāng)前負(fù)載為PAT(Program Association Table)。PAT數(shù)據(jù)的信息可以理解為整個(gè)TS流包含的節(jié)目信息。
| // Program Association Table typedef?struct?PAT_Packet_tag { ????unsigned table_id??????????????????????? : 8; //固定為0x00 ,標(biāo)志是該表是PAT ????unsigned section_syntax_indicator??????? : 1; //段語法標(biāo)志位,固定為1 ????unsigned zero??????????????????????????? : 1; //0 ????unsigned reserved_1????????????????????? : 2; // 保留位 ????unsigned section_length????????????????? : 12;//表示這個(gè)字節(jié)后面有用的字節(jié)數(shù),包括CRC32 ????unsigned transport_stream_id???????????? : 16;//該傳輸流的ID,區(qū)別于一個(gè)網(wǎng)絡(luò)中其它多路復(fù)用的流 ????unsigned reserved_2????????????????????? : 2; // 保留位 ????unsigned version_number????????????????? : 5; //范圍0-31,表示PAT的版本號(hào) ????unsigned current_next_indicator????????? : 1; //發(fā)送的PAT是當(dāng)前有效還是下一個(gè)PAT有效 ????unsigned section_number????????????????? : 8; //分段的號(hào)碼。PAT可能分為多段傳輸,第一段為00,以后每個(gè)分段加1,最多可能有256個(gè)分段 ????unsigned last_section_number???????????? : 8; //最后一個(gè)分段的號(hào)碼 ????// for(i=0; i<N; i++) ????// { ????unsigned program_number????????????????? : 16; ????unsigned reserved_3????????????????????? : 3; ????unsigned network_PID???????????????????? : 16;? // 或者program_map_PID // } ????unsigned CRC_32????????????????????????? : 32; } PAT_Packet; // Parse PAT int?Parse_PAT(unsignedchar?*pTSBuf, PAT_Packet *packet) { ????TS_header TSheader; ????if?(Parse_TS_packet_header(pTSBuf, &TSheader) != 0) ????????return?-1; ????if?(TSheader.payload_unit_start_indicator == 0x01) // 表示含有PSI或者PES頭 ????{ ????????if?(TSheader.PID == 0x0)? // 表示PAT ????????{ ?????????????int?iBeginlen = 4; ?????????????int?adaptation_field_length = pTSBuf[4]; ?????????????switch(TSheader.adaption_field_control) ?????????????{ ?????????????case?0x0:???????????????????????????????????// reserved for future use by ISO/IEC ??????????????????return?-1; ?????????????case?0x1:???????????????????????????????????// 無調(diào)整字段,僅含有效負(fù)載?????? ??????????????????iBeginlen += pTSBuf[iBeginlen] + 1;? // + pointer_field ??????????????????break; ?????????????case?0x2:????????????????????????????????????// 僅含調(diào)整字段,無有效負(fù)載 ??????????????????return?-1; ?????????????case?0x3:// 調(diào)整字段后含有效負(fù)載 ?????????????????if?(adaptation_field_length > 0) ?????????????????{ ??????????????????????iBeginlen += 1;?????????????????? // adaptation_field_length占8位 ??????????????????????iBeginlen += adaptation_field_length; // + adaptation_field_length ?????????????????} ?????????????????else ?????????????????{ ??????????????????????iBeginlen += 1;?????????????????????? // adaptation_field_length占8位 ?????????????????} ?????????????????iBeginlen += pTSBuf[iBeginlen] + 1;?????????? // + pointer_field ?????????????????break; ????????????default: ?????????????????break; ????????????} ????????????unsignedchar?*pPAT = pTSBuf + iBeginlen; ????????????packet->table_id??????????????????? = pPAT[0]; ????????????packet->section_syntax_indicator??? = pPAT[1] >> 7; ????????????packet->zero??????????????????????? = pPAT[1] >> 6 & 0x1; ????????????packet->reserved_1????????????????? = pPAT[1] >> 4 & 0x3; ????????????packet->section_length????????????? = (pPAT[1] & 0x0F) << 8 |pPAT[2]; ????????????packet->transport_stream_id???????? = pPAT[3] << 8 | pPAT[4]; ????????????packet->reserved_2????????????????? = pPAT[5] >> 6; ????????????packet->version_number????????????? = pPAT[5] >> 1 &? 0x1F; ????????????packet->current_next_indicator????? = (pPAT[5] << 7) >> 7; ????????????packet->section_number????????????? = pPAT[6]; ????????????packet->last_section_number???????? = pPAT[7]; ????????????int?len = 0; ????????????len = 3 + packet->section_length; ????????????packet->CRC_32????????????????????? = (pPAT[len-4] & 0x000000FF) << 24 ????????????????????????????????????????????????| (pPAT[len-3] & 0x000000FF) << 16 ????????????????????????????????????????????????| (pPAT[len-2] & 0x000000FF) << 8 ????????????????????????????????????????????????| (pPAT[len-1] & 0x000000FF); ????????????int?n = 0; ????????????for?( n = 0; n < (packet->section_length - 12); n += 4 ) ????????????{ ?????????????????packet->program_number = pPAT[8 + n ] << 8 | pPAT[9 + n ]; ?????????????????packet->reserved_3??????????????? = pPAT[10 + n ] >> 5; ?????????????????if?( packet->program_number == 0x00) ?????????????????{ ?????????????????????packet->network_PID = (pPAT[10 + n ] & 0x1F) << 8 |pPAT[11 + n ]; ?????????????????} ?????????????????else ?????????????????{ ?????????????????????// 有效的PMT的PID,然后通過這個(gè)PID值去查找PMT包 ?????????????????????program_map_PID = (pPAT[10 + n] & 0x1F) << 8 |pPAT[11 + n]; ?????????????????} ????????????} ????????????return?0; ?????????} ????} ????return?-1; } |
PAT數(shù)據(jù)解析需要參考:ISO/IEC 13818-1的2.4.4.3 Program Association Table
4.2 PMT解析
??? 由PAT包中的program_map_PID可以確定PMT(Program Map Table)的PID。PMT數(shù)據(jù)的信息可以理解為這個(gè)節(jié)目包含的音頻和視頻信息。?
???
| // Program Map Table typedef?struct?PMT_Packet_tag { ?????unsigned table_id??????????????????????? : 8; ?????unsigned section_syntax_indicator??????? : 1; ?????unsigned zero??????????????????????????? : 1; ?????unsigned reserved_1????????????????????? : 2; ?????unsigned section_length????????????????? : 12; ?????unsigned program_number????????????????? : 16; ?????unsigned reserved_2????????????????????? : 2; ?????unsigned version_number????????????????? : 5; ?????unsigned current_next_indicator????????? : 1; ?????unsigned section_number????????????????? : 8; ?????unsigned last_section_number???????????? : 8; ?????unsigned reserved_3????????????????????? : 3; ?????unsigned PCR_PID???????????????????????? : 13; ?????unsigned reserved_4????????????????????? : 4; ?????unsigned program_info_length???????????? : 12; ?????// for(i=0; i<N; i++) ?????// { ?????unsigned stream_type???????????????????? : 8; ?????unsigned reserved_5????????????????????? : 3; ?????unsigned elementary_PID????????????????? : 13; ?????unsigned reserved_6????????????????????? : 4; ?????unsigned ES_info_length????????????????? : 12; ?????// } ?????unsigned CRC_32????????????????????????? : 32; } PMT_Packet; ???// Parse PMT int?Parse_PMT(unsignedchar?*pTSBuf, PMT_Packet *packet) { ????// 參考Parse_PAT()來做就行了 ????// ... ????? ????return?0; } |
PMT數(shù)據(jù)解析需要參考:ISO/IEC 13818-1的2.4.4.8 Program Map Table
4.3 PES解析
??? 根據(jù)文檔參考PAT、PMT的解析流程就能完成PES的解析了。
??? 需要注意的是PES中PTS的解析,一般來說在90 kHz 中,PTS/9000的值為秒單位。
????
| unsignedlong?long?Parse_PTS(unsigned *pBuf) { ?????unsignedlong?long?llpts = (((unsigned long?long)(pBuf[0] & 0x0E)) << 29) ?????????| (unsigned long?long)(pBuf[1] << 22) ?????????| (((unsigned long?long)(pBuf[2] & 0xFE)) << 14) ?????????| (unsigned long?long)(pBuf[3] << 7) ?????????| (unsigned long?long)(pBuf[4] >> 1); ?????return?llpts; } PES結(jié)構(gòu)詳解 2013年08月05日???編程?? 共 1100字???評(píng)論數(shù) 2?? 被圍觀 3,562+ PES是Packetized Elementary Stream的簡稱,是將原始ES流打包后形成的,再將PES經(jīng)過不同的打包方式可以組成MPEG program stream 和 MPEG transport stream,即PS流和TS流。 PES的組成結(jié)構(gòu)如圖,包括6個(gè)字節(jié)的包頭字段,加上3個(gè)字節(jié)基本流信息字段,根據(jù)信息字段的設(shè)置可在之后附加其他字段。 <a href="http://www.yunlipiao.com/wp-content/uploads/2013/08/pes.jpg" class="cboxElement" rel="example4" 208"="" style="text-decoration: none; color: rgb(1, 150, 227);">PES結(jié)構(gòu) 前三字節(jié)是包頭起始標(biāo)識(shí)字段,內(nèi)容為0x000001 第四個(gè)字節(jié)是流ID字段,不同的流ID有不用的意義,如圖,音頻流ID范圍從0xC0到0xDF,視頻流ID范圍從0xE0到0xEF。 PES流ID字段 第五六個(gè)字節(jié)是PES包長度,表示PES包頭部在該字段之后的長度,單位是字節(jié) 接下來的第七八九字節(jié)是PES的擴(kuò)展頭部字段,用于設(shè)置流的基本信息,結(jié)構(gòu)如圖 PES可選擴(kuò)展 第六字節(jié)的高兩位是標(biāo)識(shí)位,值為10b 第七字節(jié)的高兩位是PTS和DTS指示位,00表示無PTS無DTS,01禁止使用,10表示PES頭部字段會(huì)附加PTS結(jié)構(gòu) pts結(jié)構(gòu) 11表示PES頭部字段會(huì)附加PTS和DTS結(jié)構(gòu) pts和dts結(jié)構(gòu) 其中PTS和DTS使用的是90KHZ時(shí)鐘單位,即1PTS表示1/90000秒,PTS和DTS雖然是33位,但占用了5個(gè)字節(jié) ESCR FLAG字段設(shè)為1,會(huì)在頭部附加6個(gè)字節(jié)的ESCR結(jié)構(gòu),ES RATE FLAG字段設(shè)置為1,會(huì)在頭部附加3個(gè)字節(jié)ES rate結(jié)構(gòu),其他標(biāo)識(shí)位如果設(shè)置為1也會(huì)相應(yīng)的在頭部附加對應(yīng)字段。 ES rate結(jié)構(gòu) ESCR結(jié)構(gòu) ? 本文地址:http://www.yunlipiao.com/208.html,出自云里飄博客,轉(zhuǎn)載請保留鏈接 |
轉(zhuǎn)載于:https://www.cnblogs.com/jukan/p/5290239.html
總結(jié)
- 上一篇: linkit-smart-7688-fe
- 下一篇: xcode 7.2 怎么在Playgro