您的位置 首页 > 雕刻工具

ts文件?ts文件格式解析

其实ts文件的问题并不复杂,但是又很多的朋友都不太了解ts文件格式解析,因此呢,今天小编就来为大家分享ts文件的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

TS:全称为MPEG2-TS。TS即"TransportStream"的缩写。它是分包发送的,每一个包长为188字节(还有192和204个字节的包)。包的结构为,包头为4个字节(第一个字节为0x47),负载为184个字节。在TS流里可以填入很多类型的数据,如视频、音频、自定义信息等。MPEG2-TS主要应用于实时传送的节目,比如实时广播的电视节目。MPEG2-TS格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。简单地说,将DVD上的VOB文件的前面一截cut掉(或者是数据损坏数据)就会导致整个文件无法解码,而电视节目是任何时候打开电视机都能解码(收看)的。

一段TS流,必须包含PAT包、PMT包、多个音频包、多个视频包、多个PCR包、以及其他信息包。

解析TS流数据的流程:查找PID为0x0的包,解析PAT,PAT包中的program_map_PID表示PMT的PID;查找PMT,PMT包中的elementary_PID表示音视频包的PID,PMT包中的PCR_PID表示PCR的PID,有的时候PCR的PID跟音频或者视频的PID相同,说明PCR会融进音视频的包,注意解析,有的时候PCR是自己单独的包;CAT、NIT、SDT、EIT的PID分别为:0x01、0x10、0x11、0x12。

//TransportStreamheader\ntypedefstructTS_header\n{\nunsignedsync_byte:8;//同步字节,固定为0x47,表示后面的是一个TS分组,当然,后面包中的数据是不会出现0x47的\nunsignedtransport_error_indicator:1;//传输错误标志位,一般传输错误的话就不会处理这个包了\nunsignedpayload_unit_start_indicator:1;//有效负载的开始标志,根据后面有效负载的内容不同功能也不同\n//payload_unit_start_indicator为1时,在前4个字节之后会有一个调整字节,它的数值决定了负载内容的具体开始位置。\nunsignedtransport_priority:1;//传输优先级位,1表示高优先级\nunsignedPID:13;//有效负载数据的类型\nunsignedtransport_scrambling_control:2;//加密标志位,00表示未加密\nunsignedadaption_field_control:2;//调整字段控制,。01仅含有效负载,10仅含调整字段,11含有调整字段和有效负载。为00的话解码器不进行处理。\nunsignedcontinuity_counter:4;//一个4bit的计数器,范围0-15\n}TS_header;\n//特殊参数说明:\n//sync_byte:0x47\n//payload_unit_start_indicator:0x01表示含有PSI或者PES头\n//PID:0x0表示后面负载内容为PAT,不同的PID表示不同的负载\n//adaption_field_control:\n//0x0://reservedforfutureusebyISO/IEC\n//0x1://无调整字段,仅含有效负载\n//0x2://仅含调整字段,无有效负载\n//0x3://调整字段后含有效负载\n\n//ParseTSheader\nintParse_TS_header(unsignedchar*pTSBuf,TS_header*pheader)\n{\npheader->sync_byte=pTSBuf[0];\nif(pheader->sync_byte!=0x47)\nreturn-1;\npheader->transport_error_indicator=pTSBuf[1]>>7;\npheader->payload_unit_start_indicator=pTSBuf[1]>>6&0x01;\npheader->transport_priority=pTSBuf[1]>>5&0x01;\npheader->PID=(pTSBuf[1]&0x1F)<<8|pTSBuf[2];\npheader->transport_scrambling_control=pTSBuf[3]>>6;\npheader->adaption_field_control=pTSBuf[3]>>4&0x03;\npheader->continuity_counter=pTSBuf[3]&0x0F;\nreturn0;\n}4.TS负载格式解析

4.1PAT解析

领取音视频开发学习资料:https://docs.qq.com/doc/DQm1VTHBlQmdmTlN2

TS_header包头中的PID值为0x0,表示当前负载为PAT(ProgramAssociationTable)。PAT数据的信息可以理解为整个TS流包含的节目信息。

//ProgramAssociationTable\ntypedefstructPAT_Packet_tag\n{\nunsignedtable_id:8;//固定为0x00,标志是该表是PAT\nunsignedsection_syntax_indicator:1;//段语法标志位,固定为1\nunsignedzero:1;//0\nunsignedreserved_1:2;//保留位\nunsignedsection_length:12;//表示有用的字节数,包括CRC32\nunsignedtransport_stream_id:16;//该传输流的ID,区别于一个网络中其它多路复用的流\nunsignedreserved_2:2;//保留位\nunsignedversion_number:5;//范围0-31,表示PAT的版本号\nunsignedcurrent_next_indicator:1;//发送的PAT是当前有效还是下一个PAT有效\nunsignedsection_number:8;//分段的号码。PAT可能分为多段传输,第一段为00,以后每个分段加1,最多可能有256个分段\nunsignedlast_section_number:8;//最后一个分段的号码\n//for(i=0;i<N;i++)\n//{\nunsignedprogram_number:16;\nunsignedreserved_3:3;\nunsignednetwork_PID:13;//或者program_map_PID\n//}\nunsignedCRC_32:32;\n}PAT_Packet;\n\n//ParsePAT\nintParse_PAT(unsignedchar*pTSBuf,PAT_Packet*packet)\n{\nTS_headerTSheader;\nif(Parse_TS_packet_header(pTSBuf,&TSheader)!=0)\nreturn-1;\nif(TSheader.payload_unit_start_indicator==0x01)//表示含有PSI或者PES头\n{\nif(TSheader.PID==0x0)//表示PAT\n{\nintiBeginlen=4;\nintadaptation_field_length=pTSBuf[4];\nswitch(TSheader.adaption_field_control)\n{\ncase0x0://reservedforfutureusebyISO/IEC\nreturn-1;\ncase0x1://无调整字段,仅含有效负载\niBeginlen+=pTSBuf[iBeginlen]+1;//+pointer_field\nbreak;\ncase0x2://仅含调整字段,无有效负载\nreturn-1;\ncase0x3://调整字段后含有效负载\nif(adaptation_field_length>0)\n{\niBeginlen+=1;//adaptation_field_length占8位\niBeginlen+=adaptation_field_length;//+adaptation_field_length\n}\nelse\n{\niBeginlen+=1;//adaptation_field_length占8位\n}\niBeginlen+=pTSBuf[iBeginlen]+1;//+pointer_field\nbreak;\ndefault:\nbreak;\n}\nunsignedchar*pPAT=pTSBuf+iBeginlen;\npacket->table_id=pPAT[0];\npacket->section_syntax_indicator=pPAT[1]>>7;\npacket->zero=pPAT[1]>>6&0x1;\npacket->reserved_1=pPAT[1]>>4&0x3;\npacket->section_length=(pPAT[1]&0x0F)<<8|pPAT[2];\npacket->transport_stream_id=pPAT[3]<<8|pPAT[4];\npacket->reserved_2=pPAT[5]>>6;\npacket->version_number=pPAT[5]>>1&0x1F;\npacket->current_next_indicator=(pPAT[5]<<7)>>7;\npacket->section_number=pPAT[6];\npacket->last_section_number=pPAT[7];\nintlen=0;\nlen=3+packet->section_length;\npacket->CRC_32=(pPAT[len-4]&0x000000FF)<<24\n|(pPAT[len-3]&0x000000FF)<<16\n|(pPAT[len-2]&0x000000FF)<<8\n|(pPAT[len-1]&0x000000FF);\n\nintn=0;\nfor(n=0;n<(packet->section_length-12);n+=4)\n{\npacket->program_number=pPAT[8+n]<<8|pPAT[9+n];\npacket->reserved_3=pPAT[10+n]>>5;\nif(packet->program_number==0x00)\n{\npacket->network_PID=(pPAT[10+n]&0x1F)<<8|pPAT[11+n];\n}\nelse\n{\n//有效的PMT的PID,然后通过这个PID值去查找PMT包\nprogram_map_PID=(pPAT[10+n]&0x1F)<<8|pPAT[11+n];\n}\n}\nreturn0;\n}\n}\nreturn-1;\n}

4.2PMT解析

由PAT包中的program_map_PID可以确定PMT(ProgramMapTable)的PID。PMT数据的信息可以理解为这个节目包含的音频和视频信息。

//ProgramMapTable\ntypedefstructPMT_Packet_tag\n{\nunsignedtable_id:8;\nunsignedsection_syntax_indicator:1;\nunsignedzero:1;\nunsignedreserved_1:2;\nunsignedsection_length:12;\nunsignedprogram_number:16;\nunsignedreserved_2:2;\nunsignedversion_number:5;\nunsignedcurrent_next_indicator:1;\nunsignedsection_number:8;\nunsignedlast_section_number:8;\nunsignedreserved_3:3;\nunsignedPCR_PID:13;\nunsignedreserved_4:4;\nunsignedprogram_info_length:12;\n//for(i=0;i<N;i++)\n//{\nunsignedstream_type:8;\nunsignedreserved_5:3;\nunsignedelementary_PID:13;\nunsignedreserved_6:4;\nunsignedES_info_length:12;\n//}\nunsignedCRC_32:32;\n}PMT_Packet;\n//ParsePMT\nintParse_PMT(unsignedchar*pTSBuf,PMT_Packet*packet)\n{\n//参考Parse_PAT()来做就行了\n//...\n\nreturn0;\n}

4.3PES解析

根据文档参考PAT、PMT的解析流程就能完成PES的解析了。

需要注意的是PES中PTS的解析,一般来说在90kHz中,PTS/9000的值为秒单位。

unsignedlonglongParse_PTS(unsigned*pBuf)\n{\nunsignedlonglongllpts=(((unsignedlonglong)(pBuf[0]&0x0E))<<29)\n|(unsignedlonglong)(pBuf[1]<<22)\n|(((unsignedlonglong)(pBuf[2]&0xFE))<<14)\n|(unsignedlonglong)(pBuf[3]<<7)\n|(unsignedlonglong)(pBuf[4]>>1);\nreturnllpts;\n}PES结构详解

领取音视频开发学习资料:https://docs.qq.com/doc/DQm1VTHBlQmdmTlN2

//生成pes头数据\nbuffer[0]=0x00;\nbuffer[1]=0x00;\nbuffer[2]=0x01;\nbuffer[3]=(unsignedchar)(pes->stream_id);\n\nbuffer[4]=(unsignedchar)((pes_header_len_syt>>8)&0xff);\nbuffer[5]=(unsignedchar)(pes_header_len_syt&0xff);\n\n\tbuffer[6]=(1<<7)//2-checkbits'10'\n|((prc->encrypt&0x03)<<4)//2-PES_scrambling_control(0)\n|((pes_priority&1)<<3)//1-PES_priority(0)\n|(((~stuff_flag)<<1)&0x04)//1-data_alignment_indicator(0)\t\n\t\t\t|0//1-copyright(0)\n\t\t\t\t|0;//1-original_or_copy(0)\n\n\tbuffer[7]=(((unsignedchar)pes->add_pts)<<7)|((unsignedchar)pes->add_user_data);\n//\tbuffer[7]=((unsignedchar)pes->add_pts)<<7;\n//2-PTS_DTS_flags()\n\t\t\t\t\t//1-ESCR_flag(0)\n\t\t\t\t\t//1-ES_rate_flag(0)\n\t\t\t\t\t//1-DSM_trick_mode_flag(0)\n\t\t\t\t\t//1-additional_copy_info_flag(0)\n\t\t\t\t\t//1-PES_CRC_flag(0)\n\t\t\t\t\t//1-PES_extension_flag()\n\t\nbuffer[8]=(unsignedchar)pes_header_ext_len;\t//8-PES_header_data_length\t\t\t\t\n\npos=9;\nif(pes->add_pts)\n{\npts=prc->ptime_stamp;\nbuffer[pos++]=(pts>>28&0x0e)|0x21;\t//4-'0010'\n\t\t\t\t\t\t\t\t\t\t\t\t//3-PTS[32..30]\n\t\t\t\t\t\t\t\t\t\t\t\t//1-marker_bit\n\tbuffer[pos++]=(pts>>21);\t\t\t\t\t//8-PTS[29..22]\n\tbuffer[pos++]=(pts>>13&0xfe)|0x01;\t//7-PTS[21..15]\n\t\t\t\t\t\t\t\t\t\t\t\t//1-marker_bit\n\tbuffer[pos++]=(pts>>6);\t\t\t\t\t//8-PTS[14..7]\n\tbuffer[pos++]=(pts<<2&0xfc)|0x01;\t//7-PTS[6..0]\n\t\t\t\t\t\t\t\t\t//1-marker_bit\n}\n

接收方PTS时间戳的获取PTS和DTS字段,本来有效信息是33位,扩展至5个字节,也就是40位。扩展方式:

通过上边这个图可以清楚地看到,PTS的33位的各部分,如果从左至右的绿色部分分别为PTS1,PTS2,PTS3的话,那么PTS的计算:

PTS=(PTS1&0x0e)<<29+(PTS2&0xfffe)<<14+(PTS3&0xfffe)>>1;

DTS(如果有)紧接着后边读取5个字节的数据,也是这样求出来的。

关于ts文件和ts文件格式解析的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023