mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
feat: plugin can use diffent loglevel
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user