h265.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package track
  2. import (
  3. "go.uber.org/zap"
  4. "m7s.live/engine/v4/codec"
  5. . "m7s.live/engine/v4/common"
  6. "m7s.live/engine/v4/log"
  7. "m7s.live/engine/v4/util"
  8. )
  9. var _ SpesificTrack = (*H265)(nil)
  10. type H265 struct {
  11. Video
  12. VPS []byte `json:"-" yaml:"-"`
  13. }
  14. func NewH265(puber IPuber, stuff ...any) (vt *H265) {
  15. vt = &H265{}
  16. vt.Video.CodecID = codec.CodecID_H265
  17. vt.SetStuff("h265", byte(96), uint32(90000), vt, stuff, puber)
  18. if vt.BytesPool == nil {
  19. vt.BytesPool = make(util.BytesPool, 17)
  20. }
  21. vt.ParamaterSets = make(ParamaterSets, 3)
  22. vt.nalulenSize = 4
  23. vt.dtsEst = util.NewDTSEstimator()
  24. return
  25. }
  26. func (vt *H265) WriteSliceBytes(slice []byte) {
  27. if len(slice) == 0 {
  28. vt.Error("H265 WriteSliceBytes got empty slice")
  29. return
  30. }
  31. t := codec.ParseH265NALUType(slice[0])
  32. if log.Trace {
  33. vt.Trace("naluType", zap.Uint8("naluType", byte(t)))
  34. }
  35. switch t {
  36. case codec.NAL_UNIT_VPS:
  37. vt.VPS = slice
  38. vt.ParamaterSets[0] = slice
  39. case codec.NAL_UNIT_SPS:
  40. vt.SPS = slice
  41. vt.ParamaterSets[1] = slice
  42. spsInfo, _ := codec.ParseHevcSPS(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. case codec.NAL_UNIT_PPS:
  48. vt.PPS = slice
  49. vt.ParamaterSets[2] = slice
  50. if vt.VPS != nil && vt.SPS != nil && vt.PPS != nil {
  51. extraData, err := codec.BuildH265SeqHeaderFromVpsSpsPps(vt.VPS, vt.SPS, vt.PPS)
  52. if err == nil {
  53. vt.nalulenSize = (int(extraData[26]) & 0x03) + 1
  54. vt.Video.WriteSequenceHead(extraData)
  55. } else {
  56. vt.Error("H265 BuildH265SeqHeaderFromVpsSpsPps", zap.Error(err))
  57. // vt.Stream.Close()
  58. }
  59. }
  60. case
  61. codec.NAL_UNIT_CODED_SLICE_BLA,
  62. codec.NAL_UNIT_CODED_SLICE_BLANT,
  63. codec.NAL_UNIT_CODED_SLICE_BLA_N_LP,
  64. codec.NAL_UNIT_CODED_SLICE_IDR,
  65. codec.NAL_UNIT_CODED_SLICE_IDR_N_LP,
  66. codec.NAL_UNIT_CODED_SLICE_CRA:
  67. vt.Value.IFrame = true
  68. vt.AppendAuBytes(slice)
  69. case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
  70. vt.Value.IFrame = false
  71. vt.AppendAuBytes(slice)
  72. case codec.NAL_UNIT_SEI, codec.NAL_UNIT_SEI_SUFFIX:
  73. vt.AppendAuBytes(slice)
  74. case codec.NAL_UNIT_ACCESS_UNIT_DELIMITER:
  75. default:
  76. vt.Warn("nalu type not supported", zap.Uint("type", uint(t)))
  77. }
  78. }
  79. func (vt *H265) WriteSequenceHead(head []byte) (err error) {
  80. if vt.VPS, vt.SPS, vt.PPS, err = codec.ParseVpsSpsPpsFromSeqHeaderWithoutMalloc(head); err == nil {
  81. vt.ParamaterSets[0] = vt.VPS
  82. vt.ParamaterSets[1] = vt.SPS
  83. vt.ParamaterSets[2] = vt.PPS
  84. vt.SPSInfo, _ = codec.ParseHevcSPS(vt.SPS)
  85. vt.nalulenSize = (int(head[26]) & 0x03) + 1
  86. vt.Video.WriteSequenceHead(head)
  87. } else {
  88. vt.Error("H265 ParseVpsSpsPps Error")
  89. vt.Publisher.Stop(zap.Error(err))
  90. }
  91. return
  92. }
  93. func (vt *H265) WriteRTPFrame(rtpItem *util.ListItem[RTPFrame]) {
  94. defer func() {
  95. err := recover()
  96. if err != nil {
  97. vt.Error("WriteRTPFrame panic", zap.Any("err", err))
  98. vt.Publisher.Stop(zap.Any("err", err))
  99. }
  100. }()
  101. frame := &rtpItem.Value
  102. rv := vt.Value
  103. rv.RTP.Push(rtpItem)
  104. // TODO: DONL may need to be parsed if `sprop-max-don-diff` is greater than 0 on the RTP stream.
  105. var usingDonlField bool
  106. var buffer = util.Buffer(frame.Payload)
  107. switch frame.H265Type() {
  108. case codec.NAL_UNIT_RTP_AP:
  109. buffer.ReadUint16()
  110. if usingDonlField {
  111. buffer.ReadUint16()
  112. }
  113. for buffer.CanRead() {
  114. l := int(buffer.ReadUint16())
  115. if buffer.CanReadN(l) {
  116. vt.WriteSliceBytes(buffer.ReadN(l))
  117. } else {
  118. return
  119. }
  120. if usingDonlField {
  121. buffer.ReadByte()
  122. }
  123. }
  124. case codec.NAL_UNIT_RTP_FU:
  125. if !buffer.CanReadN(3) {
  126. return
  127. }
  128. first3 := buffer.ReadN(3)
  129. fuHeader := first3[2]
  130. if usingDonlField {
  131. buffer.ReadUint16()
  132. }
  133. if naluType := fuHeader & 0b00111111; util.Bit1(fuHeader, 0) {
  134. vt.WriteSliceByte(first3[0]&0b10000001|(naluType<<1), first3[1])
  135. }
  136. if rv.AUList.Pre != nil {
  137. rv.AUList.Pre.Value.Push(vt.BytesPool.GetShell(buffer))
  138. }
  139. default:
  140. vt.WriteSliceBytes(frame.Payload)
  141. }
  142. if frame.Marker {
  143. vt.generateTimestamp(frame.Timestamp)
  144. if !vt.dcChanged && rv.IFrame {
  145. vt.insertDCRtp()
  146. }
  147. vt.Flush()
  148. }
  149. }
  150. func (vt *H265) CompleteAVCC(rv *AVFrame) {
  151. mem := vt.BytesPool.Get(8)
  152. b := mem.Value
  153. if rv.IFrame {
  154. b[0] = 0b1001_0000 | byte(codec.PacketTypeCodedFrames)
  155. } else {
  156. b[0] = 0b1010_0000 | byte(codec.PacketTypeCodedFrames)
  157. }
  158. util.BigEndian.PutUint32(b[1:], codec.FourCC_H265_32)
  159. // println(rv.PTS < rv.DTS, "\t", rv.PTS, "\t", rv.DTS, "\t", rv.PTS-rv.DTS)
  160. // 写入CTS
  161. util.PutBE(b[5:8], (rv.PTS-rv.DTS)/90)
  162. rv.AVCC.Push(mem)
  163. // if rv.AVCC.ByteLength != 5 {
  164. // panic("error")
  165. // }
  166. // var tmp = 0
  167. rv.AUList.Range(func(au *util.BLL) bool {
  168. mem = vt.BytesPool.Get(4)
  169. // println(au.ByteLength)
  170. util.PutBE(mem.Value, uint32(au.ByteLength))
  171. rv.AVCC.Push(mem)
  172. au.Range(func(slice util.Buffer) bool {
  173. rv.AVCC.Push(vt.BytesPool.GetShell(slice))
  174. return true
  175. })
  176. // tmp += 4 + au.ByteLength
  177. // if rv.AVCC.ByteLength != 5+tmp {
  178. // panic("error")
  179. // }
  180. return true
  181. })
  182. }
  183. // RTP格式补完
  184. func (vt *H265) CompleteRTP(value *AVFrame) {
  185. // H265打包: https://blog.csdn.net/fanyun_01/article/details/114234290
  186. var out [][][]byte
  187. if value.IFrame {
  188. out = append(out, [][]byte{vt.VPS}, [][]byte{vt.SPS}, [][]byte{vt.PPS})
  189. }
  190. vt.Value.AUList.Range(func(au *util.BLL) bool {
  191. if au.ByteLength < RTPMTU {
  192. out = append(out, au.ToBuffers())
  193. } else {
  194. startIndex := len(out)
  195. var naluType codec.H265NALUType
  196. r := au.NewReader()
  197. b0, _ := r.ReadByte()
  198. b1, _ := r.ReadByte()
  199. naluType = naluType.Parse(b0)
  200. b0 = (byte(codec.NAL_UNIT_RTP_FU) << 1) | (b0 & 0b10000001)
  201. for bufs := r.ReadN(RTPMTU); len(bufs) > 0; bufs = r.ReadN(RTPMTU) {
  202. out = append(out, append([][]byte{{b0, b1, byte(naluType)}}, bufs...))
  203. }
  204. out[startIndex][0][2] |= 1 << 7 // set start bit
  205. out[len(out)-1][0][2] |= 1 << 6 // set end bit
  206. }
  207. return true
  208. })
  209. vt.PacketizeRTP(out...)
  210. }
  211. func (vt *H265) GetNALU_SEI() (item *util.ListItem[util.Buffer]) {
  212. item = vt.BytesPool.Get(1)
  213. item.Value[0] = 0b10000000 | byte(codec.NAL_UNIT_SEI<<1)
  214. return
  215. }