subscriber.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package rtsp
  2. import (
  3. "fmt"
  4. "github.com/bluenviron/gortsplib/v4"
  5. "github.com/bluenviron/gortsplib/v4/pkg/description"
  6. "github.com/bluenviron/gortsplib/v4/pkg/format"
  7. "github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
  8. . "m7s.live/engine/v4"
  9. "m7s.live/engine/v4/codec"
  10. "m7s.live/engine/v4/track"
  11. )
  12. type RTSPSubscriber struct {
  13. Subscriber
  14. RTSPIO
  15. }
  16. func (s *RTSPSubscriber) OnEvent(event any) {
  17. switch v := event.(type) {
  18. case *track.Video:
  19. if s.Video != nil {
  20. return
  21. }
  22. switch v.CodecID {
  23. case codec.CodecID_H264:
  24. s.videoTrack = &description.Media{
  25. Type: description.MediaTypeVideo,
  26. Formats: []format.Format{&format.H264{
  27. PacketizationMode: 1,
  28. PayloadTyp: v.PayloadType,
  29. SPS: v.ParamaterSets[0],
  30. PPS: v.ParamaterSets[1],
  31. }},
  32. }
  33. case codec.CodecID_H265:
  34. s.videoTrack = &description.Media{
  35. Type: description.MediaTypeVideo,
  36. Formats: []format.Format{&format.H265{
  37. PayloadTyp: v.PayloadType,
  38. VPS: v.ParamaterSets[0],
  39. SPS: v.ParamaterSets[1],
  40. PPS: v.ParamaterSets[2],
  41. }},
  42. }
  43. case codec.CodecID_AV1:
  44. var idx, profile, tail int
  45. idx = int(v.ParamaterSets[1][0])
  46. profile = int(v.ParamaterSets[1][1])
  47. tail = int(v.ParamaterSets[1][2])
  48. s.videoTrack = &description.Media{
  49. Type: description.MediaTypeVideo,
  50. Formats: []format.Format{&format.AV1{
  51. PayloadTyp: v.PayloadType,
  52. LevelIdx: &idx,
  53. Profile: &profile,
  54. Tier: &tail,
  55. }},
  56. }
  57. }
  58. if s.videoTrack != nil {
  59. s.tracks = append(s.tracks, s.videoTrack)
  60. s.AddTrack(v)
  61. }
  62. case *track.Audio:
  63. if s.Audio != nil {
  64. return
  65. }
  66. switch v.CodecID {
  67. case codec.CodecID_AAC:
  68. s.audioTrack = &description.Media{
  69. Type: description.MediaTypeAudio,
  70. Formats: []format.Format{&format.MPEG4Audio{
  71. PayloadTyp: v.PayloadType,
  72. Config: &mpeg4audio.Config{
  73. Type: mpeg4audio.ObjectTypeAACLC,
  74. SampleRate: int(v.SampleRate),
  75. ChannelCount: int(v.Channels),
  76. },
  77. SizeLength: v.SizeLength,
  78. IndexLength: v.IndexLength,
  79. IndexDeltaLength: v.IndexDeltaLength,
  80. }},
  81. }
  82. case codec.CodecID_PCMA:
  83. s.audioTrack = &description.Media{
  84. Type: description.MediaTypeAudio,
  85. Formats: []format.Format{&format.Generic{
  86. PayloadTyp: v.PayloadType,
  87. ClockRat: int(v.SampleRate),
  88. RTPMa: fmt.Sprintf("PCMA/%d", v.SampleRate),
  89. }},
  90. }
  91. case codec.CodecID_PCMU:
  92. s.audioTrack = &description.Media{
  93. Type: description.MediaTypeAudio,
  94. Formats: []format.Format{&format.Generic{
  95. PayloadTyp: v.PayloadType,
  96. ClockRat: int(v.SampleRate),
  97. RTPMa: fmt.Sprintf("PCMU/%d", v.SampleRate),
  98. }},
  99. }
  100. case codec.CodecID_OPUS:
  101. s.audioTrack = &description.Media{
  102. Type: description.MediaTypeAudio,
  103. Formats: []format.Format{&format.Opus{
  104. PayloadTyp: v.PayloadType,
  105. }},
  106. }
  107. }
  108. if s.audioTrack != nil {
  109. s.tracks = append(s.tracks, s.audioTrack)
  110. s.AddTrack(v)
  111. }
  112. case ISubscriber:
  113. s.session = &description.Session{
  114. Medias: s.tracks,
  115. }
  116. if s.server != nil {
  117. s.stream = gortsplib.NewServerStream(s.server, s.session)
  118. }
  119. case VideoRTP:
  120. s.stream.WritePacketRTP(s.videoTrack, v.Packet)
  121. case AudioRTP:
  122. s.stream.WritePacketRTP(s.audioTrack, v.Packet)
  123. default:
  124. s.Subscriber.OnEvent(event)
  125. }
  126. }