publisher.go 3.4 KB

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