h264.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. package track
  2. import (
  3. "bytes"
  4. "time"
  5. "go.uber.org/zap"
  6. "m7s.live/engine/v4/codec"
  7. . "m7s.live/engine/v4/common"
  8. "m7s.live/engine/v4/log"
  9. "m7s.live/engine/v4/util"
  10. )
  11. var _ SpesificTrack = (*H264)(nil)
  12. type H264 struct {
  13. Video
  14. buf util.Buffer // rtp 包临时缓存,对于不规范的 rtp 包(sps 放到了 fua 中导致)需要缓存
  15. }
  16. func NewH264(puber IPuber, stuff ...any) (vt *H264) {
  17. vt = &H264{}
  18. vt.Video.CodecID = codec.CodecID_H264
  19. vt.SetStuff("h264", byte(96), uint32(90000), vt, stuff, puber)
  20. if vt.BytesPool == nil {
  21. vt.BytesPool = make(util.BytesPool, 17)
  22. }
  23. vt.ParamaterSets = make(ParamaterSets, 2)
  24. vt.nalulenSize = 4
  25. vt.dtsEst = util.NewDTSEstimator()
  26. return
  27. }
  28. func (vt *H264) WriteSliceBytes(slice []byte) {
  29. if len(slice) > 4 && bytes.Equal(slice[:4], codec.NALU_Delimiter2) {
  30. slice = slice[4:] // 有些设备厂商不规范,所以需要移除前导的 00 00 00 01
  31. }
  32. if len(slice) == 0 {
  33. vt.Error("H264 WriteSliceBytes got empty slice")
  34. return
  35. }
  36. naluType := codec.ParseH264NALUType(slice[0])
  37. if log.Trace {
  38. vt.Trace("naluType", zap.Uint8("naluType", naluType.Byte()))
  39. }
  40. switch naluType {
  41. case codec.NALU_SPS:
  42. spsInfo, _ := codec.ParseSPS(slice)
  43. if spsInfo.Width != vt.SPSInfo.Width || spsInfo.Height != vt.SPSInfo.Height {
  44. vt.Debug("SPS", zap.Any("SPSInfo", spsInfo))
  45. }
  46. vt.SPSInfo = spsInfo
  47. vt.Video.SPS = slice
  48. vt.ParamaterSets[0] = slice
  49. case codec.NALU_PPS:
  50. vt.Video.PPS = slice
  51. vt.ParamaterSets[1] = slice
  52. lenSPS := len(vt.Video.SPS)
  53. lenPPS := len(vt.Video.PPS)
  54. var b util.Buffer
  55. if lenSPS > 3 {
  56. b.Write(codec.RTMP_AVC_HEAD[:6])
  57. b.Write(vt.Video.SPS[1:4])
  58. b.Write(codec.RTMP_AVC_HEAD[9:10])
  59. } else {
  60. b.Write(codec.RTMP_AVC_HEAD)
  61. }
  62. b.WriteByte(0xE1)
  63. b.WriteUint16(uint16(lenSPS))
  64. b.Write(vt.Video.SPS)
  65. b.WriteByte(0x01)
  66. b.WriteUint16(uint16(lenPPS))
  67. b.Write(vt.Video.PPS)
  68. vt.WriteSequenceHead(b)
  69. case codec.NALU_IDR_Picture:
  70. vt.Value.IFrame = true
  71. vt.AppendAuBytes(slice)
  72. case codec.NALU_Non_IDR_Picture,
  73. codec.NALU_Data_Partition_A,
  74. codec.NALU_Data_Partition_B,
  75. codec.NALU_Data_Partition_C:
  76. vt.Value.IFrame = false
  77. vt.AppendAuBytes(slice)
  78. case codec.NALU_SEI:
  79. vt.AppendAuBytes(slice)
  80. case codec.NALU_Access_Unit_Delimiter:
  81. case codec.NALU_Filler_Data:
  82. default:
  83. if vt.Value.IFrame {
  84. vt.AppendAuBytes(slice)
  85. return
  86. }
  87. vt.Error("nalu type not support", zap.Int("type", int(naluType)))
  88. }
  89. }
  90. func (vt *H264) WriteSequenceHead(head []byte) (err error) {
  91. var info codec.AVCDecoderConfigurationRecord
  92. if _, err = info.Unmarshal(head[5:]); err == nil {
  93. vt.SPSInfo, _ = codec.ParseSPS(info.SequenceParameterSetNALUnit)
  94. vt.nalulenSize = int(info.LengthSizeMinusOne&3 + 1)
  95. vt.SPS = info.SequenceParameterSetNALUnit
  96. vt.PPS = info.PictureParameterSetNALUnit
  97. vt.ParamaterSets[0] = vt.SPS
  98. vt.ParamaterSets[1] = vt.PPS
  99. vt.Video.WriteSequenceHead(head)
  100. } else {
  101. vt.Error("H264 ParseSpsPps Error")
  102. vt.Publisher.Stop(zap.Error(err))
  103. }
  104. return
  105. }
  106. func (vt *H264) WriteRTPFrame(rtpItem *util.ListItem[RTPFrame]) {
  107. defer func() {
  108. err := recover()
  109. if err != nil {
  110. vt.Error("WriteRTPFrame panic", zap.Any("err", err))
  111. vt.Publisher.Stop(zap.Any("err", err))
  112. }
  113. }()
  114. if vt.lastSeq != vt.lastSeq2+1 && vt.lastSeq2 != 0 {
  115. vt.lostFlag = true
  116. vt.Warn("lost rtp packet", zap.Uint16("lastSeq", vt.lastSeq), zap.Uint16("lastSeq2", vt.lastSeq2))
  117. }
  118. frame := &rtpItem.Value
  119. pts := frame.Timestamp
  120. rv := vt.Value
  121. // 有些流的 rtp 包中没有设置 marker 导致无法判断是否是最后一个包,此时通过时间戳变化判断,先 flush 之前的帧
  122. if rv.PTS != time.Duration(pts) {
  123. if rv.AUList.ByteLength > 0 {
  124. if !vt.dcChanged && rv.IFrame {
  125. vt.insertDCRtp()
  126. }
  127. vt.Flush()
  128. rv = vt.Value
  129. }
  130. vt.generateTimestamp(pts)
  131. }
  132. rv.RTP.Push(rtpItem)
  133. if naluType := frame.H264Type(); naluType < 24 {
  134. vt.WriteSliceBytes(frame.Payload)
  135. } else {
  136. offset := naluType.Offset()
  137. switch naluType {
  138. case codec.NALU_STAPA, codec.NALU_STAPB:
  139. if len(frame.Payload) <= offset {
  140. vt.Error("invalid nalu size", zap.Int("naluType", int(naluType)))
  141. return
  142. }
  143. for buffer := util.Buffer(frame.Payload[offset:]); buffer.CanRead(); {
  144. nextSize := int(buffer.ReadUint16())
  145. if buffer.Len() >= nextSize {
  146. vt.WriteSliceBytes(buffer.ReadN(nextSize))
  147. } else {
  148. vt.Error("invalid nalu size", zap.Int("naluType", int(naluType)))
  149. return
  150. }
  151. }
  152. case codec.NALU_FUA, codec.NALU_FUB:
  153. b1 := frame.Payload[1]
  154. if util.Bit1(b1, 0) {
  155. naluType = naluType.Parse(b1)
  156. firstByte := naluType.Or(frame.Payload[0] & 0x60)
  157. switch naluType {
  158. case codec.NALU_SPS, codec.NALU_PPS:
  159. vt.buf.WriteByte(firstByte)
  160. default:
  161. vt.WriteSliceByte(firstByte)
  162. }
  163. }
  164. if vt.buf.Len() > 0 {
  165. vt.buf.Write(frame.Payload[offset:])
  166. } else {
  167. if rv.AUList.Pre != nil && rv.AUList.Pre.Value != nil {
  168. rv.AUList.Pre.Value.Push(vt.BytesPool.GetShell(frame.Payload[offset:]))
  169. } else {
  170. vt.Error("fu have no start")
  171. return
  172. }
  173. }
  174. if !util.Bit1(b1, 1) {
  175. // fua 还没结束
  176. return
  177. } else if vt.buf.Len() > 0 {
  178. vt.WriteAnnexB(uint32(rv.PTS), uint32(rv.DTS), vt.buf)
  179. vt.buf = nil
  180. }
  181. }
  182. }
  183. if rv = vt.Value; frame.Marker && rv.AUList.ByteLength > 0 {
  184. if !vt.dcChanged && rv.IFrame {
  185. vt.insertDCRtp()
  186. }
  187. vt.Flush()
  188. }
  189. }
  190. // RTP格式补完
  191. func (vt *H264) CompleteRTP(value *AVFrame) {
  192. var out [][][]byte
  193. if value.IFrame {
  194. out = append(out, [][]byte{vt.SPS}, [][]byte{vt.PPS})
  195. }
  196. vt.Value.AUList.Range(func(au *util.BLL) bool {
  197. if au.ByteLength < RTPMTU {
  198. out = append(out, au.ToBuffers())
  199. } else {
  200. startIndex := len(out)
  201. var naluType codec.H264NALUType
  202. r := au.NewReader()
  203. b0, _ := r.ReadByte()
  204. naluType = naluType.Parse(b0)
  205. b0 = codec.NALU_FUA.Or(b0 & 0x60)
  206. for bufs := r.ReadN(RTPMTU); len(bufs) > 0; bufs = r.ReadN(RTPMTU) {
  207. out = append(out, append([][]byte{{b0, naluType.Byte()}}, bufs...))
  208. }
  209. out[startIndex][0][1] |= 1 << 7 // set start bit
  210. out[len(out)-1][0][1] |= 1 << 6 // set end bit
  211. }
  212. return true
  213. })
  214. vt.PacketizeRTP(out...)
  215. }
  216. func (vt *H264) GetNALU_SEI() (item *util.ListItem[util.Buffer]) {
  217. item = vt.BytesPool.Get(1)
  218. item.Value[0] = byte(codec.NALU_SEI)
  219. return
  220. }