feat: plugin can use diffent loglevel

This commit is contained in:
langhuihui
2024-06-28 17:47:29 +08:00
parent 0e28086d02
commit bbe1d785ce
20 changed files with 869 additions and 374 deletions

View File

@@ -1,8 +1,14 @@
package rtsp
import (
"fmt"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/rtcp"
"github.com/pion/rtp"
"github.com/pion/webrtc/v4"
"m7s.live/m7s/v5"
mrtp "m7s.live/m7s/v5/plugin/rtp/pkg"
"reflect"
)
type Stream struct {
@@ -21,3 +27,195 @@ type Receiver struct {
AudioCodecParameters *webrtc.RTPCodecParameters
VideoCodecParameters *webrtc.RTPCodecParameters
}
func (ns *Stream) Close() error {
if ns.NetConnection != nil {
ns.NetConnection.Destroy()
}
return nil
}
func (s *Sender) GetMedia() (medias []*core.Media, err error) {
if s.SubAudio && s.Publisher.PubAudio {
audioTrack := s.Publisher.GetAudioTrack(reflect.TypeOf((*mrtp.RTPAudio)(nil)))
if err = audioTrack.WaitReady(); err != nil {
return
}
parameter := audioTrack.ICodecCtx.(mrtp.IRTPCtx).GetRTPCodecParameter()
media := &core.Media{
Kind: "audio",
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{{
Name: parameter.MimeType[6:],
ClockRate: parameter.ClockRate,
Channels: parameter.Channels,
FmtpLine: parameter.SDPFmtpLine,
PayloadType: uint8(parameter.PayloadType),
}},
ID: fmt.Sprintf("trackID=%d", len(medias)),
}
medias = append(medias, media)
s.AudioChannelID = 0
}
if s.SubVideo && s.Publisher.PubVideo {
videoTrack := s.Publisher.GetVideoTrack(reflect.TypeOf((*mrtp.RTPVideo)(nil)))
if err = videoTrack.WaitReady(); err != nil {
return
}
parameter := videoTrack.ICodecCtx.(mrtp.IRTPCtx).GetRTPCodecParameter()
c := core.Codec{
Name: parameter.MimeType[6:],
ClockRate: parameter.ClockRate,
Channels: parameter.Channels,
FmtpLine: parameter.SDPFmtpLine,
PayloadType: uint8(parameter.PayloadType),
}
media := &core.Media{
Kind: "video",
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{&c},
ID: fmt.Sprintf("trackID=%d", len(medias)),
}
s.VideoChannelID = byte(len(medias)) << 1
medias = append(medias, media)
}
return
}
func (s *Sender) Send() error {
sendRTP := func(pack *mrtp.RTPData, channel byte) (err error) {
s.StartWrite()
defer s.StopWrite()
for _, packet := range pack.Packets {
size := packet.MarshalSize()
chunk := s.MemoryAllocator.Borrow(size + 4)
chunk[0], chunk[1], chunk[2], chunk[3] = '$', channel, byte(size>>8), byte(size)
if _, err = packet.MarshalTo(chunk[4:]); err != nil {
return
}
if _, err = s.Write(chunk); err != nil {
return
}
}
return
}
go func(err error) {
for err == nil {
_, _, err = s.NetConnection.Receive(true)
}
}(nil)
return m7s.PlayBlock(s.Subscriber, func(audio *mrtp.RTPAudio) error {
return sendRTP(&audio.RTPData, s.AudioChannelID)
}, func(video *mrtp.RTPVideo) error {
return sendRTP(&video.RTPData, s.VideoChannelID)
})
}
func (r *Receiver) SetMedia(medias []*core.Media) (err error) {
for i, media := range medias {
if codec := media.Codecs[0]; codec.IsAudio() {
r.AudioCodecParameters = &webrtc.RTPCodecParameters{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: "audio/" + codec.Name,
ClockRate: codec.ClockRate,
Channels: codec.Channels,
SDPFmtpLine: codec.FmtpLine,
RTCPFeedback: nil,
},
PayloadType: webrtc.PayloadType(codec.PayloadType),
}
r.AudioChannelID = byte(i) << 1
} else if codec.IsVideo() {
r.VideoChannelID = byte(i) << 1
r.VideoCodecParameters = &webrtc.RTPCodecParameters{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: "video/" + codec.Name,
ClockRate: codec.ClockRate,
Channels: codec.Channels,
SDPFmtpLine: codec.FmtpLine,
RTCPFeedback: nil,
},
PayloadType: webrtc.PayloadType(codec.PayloadType),
}
} else {
r.Warn("media kind not support", "kind", codec.Kind())
}
}
return
}
func (r *Receiver) Receive() (err error) {
audioFrame, videoFrame := &mrtp.RTPAudio{}, &mrtp.RTPVideo{}
audioFrame.ScalableMemoryAllocator = r.MemoryAllocator
audioFrame.RTPCodecParameters = r.AudioCodecParameters
videoFrame.ScalableMemoryAllocator = r.MemoryAllocator
videoFrame.RTPCodecParameters = r.VideoCodecParameters
var channelID byte
var buf []byte
for err == nil {
channelID, buf, err = r.NetConnection.Receive(false)
if err != nil {
return
}
if len(buf) == 0 {
continue
}
if channelID&1 == 0 {
switch channelID {
case r.AudioChannelID:
if !r.PubAudio {
continue
}
packet := &rtp.Packet{}
if err = packet.Unmarshal(buf); err != nil {
return
}
if len(audioFrame.Packets) == 0 || packet.Timestamp == audioFrame.Packets[0].Timestamp {
audioFrame.AddRecycleBytes(buf)
audioFrame.Packets = append(audioFrame.Packets, packet)
} else {
err = r.WriteAudio(audioFrame)
audioFrame = &mrtp.RTPAudio{}
audioFrame.AddRecycleBytes(buf)
audioFrame.Packets = []*rtp.Packet{packet}
audioFrame.RTPCodecParameters = r.VideoCodecParameters
audioFrame.ScalableMemoryAllocator = r.MemoryAllocator
}
case r.VideoChannelID:
if !r.PubVideo {
continue
}
packet := &rtp.Packet{}
if err = packet.Unmarshal(buf); err != nil {
return
}
if len(videoFrame.Packets) == 0 || packet.Timestamp == videoFrame.Packets[0].Timestamp {
videoFrame.AddRecycleBytes(buf)
videoFrame.Packets = append(videoFrame.Packets, packet)
} else {
// t := time.Now()
err = r.WriteVideo(videoFrame)
// fmt.Println("write video", time.Since(t))
videoFrame = &mrtp.RTPVideo{}
videoFrame.AddRecycleBytes(buf)
videoFrame.Packets = []*rtp.Packet{packet}
videoFrame.RTPCodecParameters = r.VideoCodecParameters
videoFrame.ScalableMemoryAllocator = r.MemoryAllocator
}
default:
}
} else {
msg := &RTCP{Channel: channelID}
r.MemoryAllocator.Free(buf)
if err = msg.Header.Unmarshal(buf); err != nil {
return
}
if msg.Packets, err = rtcp.Unmarshal(buf); err != nil {
return
}
r.Debug("rtcp", "type", msg.Header.Type, "length", msg.Header.Length)
// TODO: rtcp msg
}
}
return
}