mpegts_pat.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. package mpegts
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "m7s.live/engine/v4/util"
  8. )
  9. // ios13818-1-CN.pdf 43(57)/166
  10. //
  11. // PAT
  12. //
  13. var DefaultPATPacket = []byte{
  14. // TS Header
  15. 0x47, 0x40, 0x00, 0x10,
  16. // Pointer Field
  17. 0x00,
  18. // PSI
  19. 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00,
  20. // PAT
  21. 0x00, 0x01, 0xe1, 0x00,
  22. // CRC
  23. 0xe8, 0xf9, 0x5e, 0x7d,
  24. // Stuffing 167 bytes
  25. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  26. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  27. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  28. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  29. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  30. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  31. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  32. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  33. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  34. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  35. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  36. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  37. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  38. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  39. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  40. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  41. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  42. }
  43. // TS Header :
  44. // SyncByte = 0x47
  45. // TransportErrorIndicator = 0(B:0), PayloadUnitStartIndicator = 1(B:0), TransportPriority = 0(B:0),
  46. // Pid = 0,
  47. // TransportScramblingControl = 0(B:00), AdaptionFieldControl = 1(B:01), ContinuityCounter = 0(B:0000),
  48. // PSI :
  49. // TableID = 0x00,
  50. // SectionSyntaxIndicator = 1(B:1), Zero = 0(B:0), Reserved1 = 3(B:11),
  51. // SectionLength = 13(0x00d)
  52. // TransportStreamID = 0x0001
  53. // Reserved2 = 3(B:11), VersionNumber = (B:00000), CurrentNextIndicator = 1(B:0),
  54. // SectionNumber = 0x00
  55. // LastSectionNumber = 0x00
  56. // PAT :
  57. // ProgramNumber = 0x0001
  58. // Reserved3 = 15(B:1110), ProgramMapPID = 4097(0x1001)
  59. // PAT表主要包含频道号码和每一个频道对应的PMT的PID号码,这些信息我们在处理PAT表格的时候会保存起来,以后会使用到这些数据
  60. type MpegTsPATProgram struct {
  61. ProgramNumber uint16 // 16 bit 节目号
  62. Reserved3 byte // 3 bits 保留位
  63. NetworkPID uint16 // 13 bits 网络信息表(NIT)的PID,节目号为0时对应的PID为network_PID
  64. ProgramMapPID uint16 // 13 bit 节目映射表的PID,节目号大于0时对应的PID.每个节目对应一个
  65. }
  66. // Program Association Table (节目关联表)
  67. // 节目号为0x0000时,表示这是NIT,PID=0x001f,即3.
  68. // 节目号为0x0001时,表示这是PMT,PID=0x100,即256
  69. type MpegTsPAT struct {
  70. // PSI
  71. TableID byte // 8 bits 0x00->PAT,0x02->PMT
  72. SectionSyntaxIndicator byte // 1 bit 段语法标志位,固定为1
  73. Zero byte // 1 bit 0
  74. Reserved1 byte // 2 bits 保留位
  75. SectionLength uint16 // 12 bits 该字段的头两比特必为'00',剩余 10 比特指定该分段的字节数,紧随 section_length 字段开始,并包括 CRC.此字段中的值应不超过 1021(0x3FD)
  76. TransportStreamID uint16 // 16 bits 该字段充当标签,标识网络内此传输流有别于任何其他多路复用流.其值由用户规定
  77. Reserved2 byte // 2 bits 保留位
  78. VersionNumber byte // 5 bits 范围0-31,表示PAT的版本号
  79. CurrentNextIndicator byte // 1 bit 发送的PAT是当前有效还是下一个PAT有效,0则要等待下一个表
  80. SectionNumber byte // 8 bits 分段的号码.PAT可能分为多段传输.第一段为00,以后每个分段加1,最多可能有256个分段
  81. LastSectionNumber byte // 8 bits 最后一个分段的号码
  82. // N Loop
  83. Program []MpegTsPATProgram // PAT表里面的所有频道索引信息
  84. Crc32 uint32 // 32 bits 包含处理全部传输流节目映射分段之后,在附件 B 规定的解码器中给出寄存器零输出的 CRC 值
  85. }
  86. func ReadPAT(r io.Reader) (pat MpegTsPAT, err error) {
  87. lr, psi, err := ReadPSI(r, PSI_TYPE_PAT)
  88. if err != nil {
  89. return
  90. }
  91. pat = psi.Pat
  92. // N Loop
  93. // 一直循环去读4个字节,用lr的原因是确保不会读过头了.
  94. for lr.N > 0 {
  95. // 获取每一个频道的节目信息,保存起来
  96. programs := MpegTsPATProgram{}
  97. programs.ProgramNumber, err = util.ReadByteToUint16(lr, true)
  98. if err != nil {
  99. return
  100. }
  101. // 如果programNumber为0,则是NetworkPID,否则是ProgramMapPID(13)
  102. if programs.ProgramNumber == 0 {
  103. programs.NetworkPID, err = util.ReadByteToUint16(lr, true)
  104. if err != nil {
  105. return
  106. }
  107. programs.NetworkPID = programs.NetworkPID & 0x1fff
  108. } else {
  109. programs.ProgramMapPID, err = util.ReadByteToUint16(lr, true)
  110. if err != nil {
  111. return
  112. }
  113. programs.ProgramMapPID = programs.ProgramMapPID & 0x1fff
  114. }
  115. pat.Program = append(pat.Program, programs)
  116. }
  117. if cr, ok := r.(*util.Crc32Reader); ok {
  118. err = cr.ReadCrc32UIntAndCheck()
  119. if err != nil {
  120. return
  121. }
  122. }
  123. return
  124. }
  125. func WritePAT(w io.Writer, pat MpegTsPAT) (err error) {
  126. bw := &bytes.Buffer{}
  127. // 将pat(所有的节目索引信息)写入到缓冲区中
  128. for _, pats := range pat.Program {
  129. if err = util.WriteUint16ToByte(bw, pats.ProgramNumber, true); err != nil {
  130. return
  131. }
  132. if pats.ProgramNumber == 0 {
  133. if err = util.WriteUint16ToByte(bw, pats.NetworkPID&0x1fff|7<<13, true); err != nil {
  134. return
  135. }
  136. } else {
  137. // | 0001 1111 | 1111 1111 |
  138. // 7 << 13 -> 1110 0000 0000 0000
  139. if err = util.WriteUint16ToByte(bw, pats.ProgramMapPID&0x1fff|7<<13, true); err != nil {
  140. return
  141. }
  142. }
  143. }
  144. if pat.SectionLength == 0 {
  145. pat.SectionLength = 2 + 3 + 4 + uint16(len(bw.Bytes()))
  146. }
  147. psi := MpegTsPSI{}
  148. psi.Pat = pat
  149. if err = WritePSI(w, PSI_TYPE_PAT, psi, bw.Bytes()); err != nil {
  150. return
  151. }
  152. return
  153. }
  154. func WritePATPacket(w io.Writer, tsHeader []byte, pat MpegTsPAT) (err error) {
  155. if pat.TableID != TABLE_PAS {
  156. err = errors.New("PAT table ID error")
  157. return
  158. }
  159. // 将所有要写的数据(PAT),全部放入到buffer中去.
  160. // buffer 里面已经写好了整个pat表(PointerField+PSI+PAT+CRC)
  161. bw := &bytes.Buffer{}
  162. if err = WritePAT(bw, pat); err != nil {
  163. return
  164. }
  165. // TODO:如果Pat.Program里面包含的信息很大,大于188?
  166. stuffingBytes := util.GetFillBytes(0xff, TS_PACKET_SIZE-4-bw.Len())
  167. // PATPacket = TsHeader + PAT + Stuffing Bytes
  168. var PATPacket []byte
  169. PATPacket = append(PATPacket, tsHeader...)
  170. PATPacket = append(PATPacket, bw.Bytes()...)
  171. PATPacket = append(PATPacket, stuffingBytes...)
  172. fmt.Println("-------------------------")
  173. fmt.Println("Write PAT :", PATPacket)
  174. fmt.Println("-------------------------")
  175. // 写PAT负载
  176. if _, err = w.Write(PATPacket); err != nil {
  177. return
  178. }
  179. return
  180. }
  181. func WriteDefaultPATPacket(w io.Writer) (err error) {
  182. _, err = w.Write(DefaultPATPacket)
  183. if err != nil {
  184. return
  185. }
  186. return
  187. }