publisher.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package engine
  2. import (
  3. "go.uber.org/zap"
  4. "m7s.live/engine/v4/codec"
  5. "m7s.live/engine/v4/common"
  6. "m7s.live/engine/v4/config"
  7. "m7s.live/engine/v4/track"
  8. "m7s.live/engine/v4/util"
  9. )
  10. type IPublisher interface {
  11. IIO
  12. GetPublisher() *Publisher
  13. getAudioTrack() common.AudioTrack
  14. getVideoTrack() common.VideoTrack
  15. Publish(streamPath string, pub IPublisher) error
  16. }
  17. var _ IPublisher = (*Publisher)(nil)
  18. type Publisher struct {
  19. IO
  20. Config *config.Publish
  21. common.AudioTrack `json:"-" yaml:"-"`
  22. common.VideoTrack `json:"-" yaml:"-"`
  23. }
  24. func (p *Publisher) Publish(streamPath string, pub IPublisher) error {
  25. return p.receive(streamPath, pub)
  26. }
  27. func (p *Publisher) GetPublisher() *Publisher {
  28. return p
  29. }
  30. // func (p *Publisher) Stop(reason ...zapcore.Field) {
  31. // p.IO.Stop(reason...)
  32. // p.Stream.Receive(ACTION_PUBLISHCLOSE)
  33. // }
  34. func (p *Publisher) getAudioTrack() common.AudioTrack {
  35. return p.AudioTrack
  36. }
  37. func (p *Publisher) getVideoTrack() common.VideoTrack {
  38. return p.VideoTrack
  39. }
  40. func (p *Publisher) Equal(p2 IPublisher) bool {
  41. return p == p2.GetPublisher()
  42. }
  43. // func (p *Publisher) OnEvent(event any) {
  44. // p.IO.OnEvent(event)
  45. // switch event.(type) {
  46. // case SEclose, SEKick:
  47. // p.AudioTrack = nil
  48. // p.VideoTrack = nil
  49. // }
  50. // }
  51. func (p *Publisher) WriteAVCCVideo(ts uint32, frame *util.BLL, pool util.BytesPool) {
  52. if frame.ByteLength < 6 {
  53. return
  54. }
  55. if p.VideoTrack == nil {
  56. b0 := frame.GetByte(0)
  57. // https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf
  58. if isExtHeader := b0 & 0b1000_0000; isExtHeader != 0 {
  59. fourCC := frame.GetUintN(1, 4)
  60. switch fourCC {
  61. case codec.FourCC_H265_32:
  62. p.VideoTrack = track.NewH265(p.Stream, pool)
  63. p.VideoTrack.WriteAVCC(ts, frame)
  64. case codec.FourCC_AV1_32:
  65. p.VideoTrack = track.NewAV1(p.Stream, pool)
  66. p.VideoTrack.WriteAVCC(ts, frame)
  67. }
  68. } else {
  69. if frame.GetByte(1) == 0 {
  70. ts = 0
  71. switch codecID := codec.VideoCodecID(b0 & 0x0F); codecID {
  72. case codec.CodecID_H264:
  73. p.VideoTrack = track.NewH264(p.Stream, pool)
  74. case codec.CodecID_H265:
  75. p.VideoTrack = track.NewH265(p.Stream, pool)
  76. default:
  77. p.Stream.Error("video codecID not support", zap.Uint8("codeId", uint8(codecID)))
  78. return
  79. }
  80. p.VideoTrack.WriteAVCC(ts, frame)
  81. } else {
  82. p.Stream.Warn("need sequence frame")
  83. }
  84. }
  85. } else {
  86. p.VideoTrack.WriteAVCC(ts, frame)
  87. }
  88. }
  89. func (p *Publisher) WriteAVCCAudio(ts uint32, frame *util.BLL, pool util.BytesPool) {
  90. if frame.ByteLength < 4 {
  91. return
  92. }
  93. if p.AudioTrack == nil {
  94. b0 := frame.GetByte(0)
  95. switch codecID := codec.AudioCodecID(b0 >> 4); codecID {
  96. case codec.CodecID_AAC:
  97. if frame.GetByte(1) != 0 {
  98. return
  99. }
  100. a := track.NewAAC(p.Stream, pool)
  101. p.AudioTrack = a
  102. a.AVCCHead = []byte{frame.GetByte(0), 1}
  103. a.WriteAVCC(0, frame)
  104. case codec.CodecID_PCMA,
  105. codec.CodecID_PCMU:
  106. alaw := true
  107. if codecID == codec.CodecID_PCMU {
  108. alaw = false
  109. }
  110. a := track.NewG711(p.Stream, alaw, pool)
  111. p.AudioTrack = a
  112. a.Audio.SampleRate = uint32(codec.SoundRate[(b0&0x0c)>>2])
  113. if b0&0x02 == 0 {
  114. a.Audio.SampleSize = 8
  115. }
  116. a.Channels = b0&0x01 + 1
  117. a.AVCCHead = []byte{b0}
  118. a.WriteAVCC(ts, frame)
  119. default:
  120. p.Stream.Error("audio codec not support yet", zap.Uint8("codecId", uint8(codecID)))
  121. }
  122. } else {
  123. p.AudioTrack.WriteAVCC(ts, frame)
  124. }
  125. }