mirror of
https://github.com/livekit/livekit.git
synced 2026-03-31 11:05:39 +00:00
102 lines
3.0 KiB
Go
102 lines
3.0 KiB
Go
package rtc
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/pion/sdp/v3"
|
|
"github.com/pion/webrtc/v3"
|
|
)
|
|
|
|
const (
|
|
mediaNameAudio = "audio"
|
|
mediaNameVideo = "video"
|
|
)
|
|
|
|
// MediaEngine handles stream codecs
|
|
type MediaEngine struct {
|
|
webrtc.MediaEngine
|
|
feedbackTypes []webrtc.RTCPFeedback
|
|
TCCExt int
|
|
}
|
|
|
|
// PopulateFromSDP finds all codecs in sd and adds them to m, using the dynamic
|
|
// payload types and parameters from sd.
|
|
// PopulateFromSDP is intended for use when answering a request.
|
|
// The offerer sets the PayloadTypes for the connection.
|
|
// PopulateFromSDP allows an answerer to properly match the PayloadTypes from the offerer.
|
|
// A MediaEngine populated by PopulateFromSDP should be used only for a single session.
|
|
func (e *MediaEngine) PopulateFromSDP(sd webrtc.SessionDescription) error {
|
|
s := sdp.SessionDescription{}
|
|
if err := s.Unmarshal([]byte(sd.SDP)); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, md := range s.MediaDescriptions {
|
|
if md.MediaName.Media != mediaNameAudio && md.MediaName.Media != mediaNameVideo {
|
|
continue
|
|
}
|
|
|
|
for _, att := range md.Attributes {
|
|
if att.Key == sdp.AttrKeyExtMap && strings.HasSuffix(att.Value, sdp.TransportCCURI) {
|
|
e.TCCExt, _ = strconv.Atoi(att.Value[:1])
|
|
break
|
|
}
|
|
}
|
|
|
|
for _, format := range md.MediaName.Formats {
|
|
pt, err := strconv.Atoi(format)
|
|
if err != nil {
|
|
return fmt.Errorf("format parse error")
|
|
}
|
|
|
|
payloadType := uint8(pt)
|
|
payloadCodec, err := s.GetCodecForPayloadType(payloadType)
|
|
if err != nil {
|
|
return fmt.Errorf("could not find codec for payload type %d", payloadType)
|
|
}
|
|
|
|
var codec *webrtc.RTPCodec
|
|
switch {
|
|
case strings.EqualFold(payloadCodec.Name, webrtc.Opus):
|
|
codec = webrtc.NewRTPOpusCodec(payloadType, payloadCodec.ClockRate)
|
|
case strings.EqualFold(payloadCodec.Name, webrtc.VP8):
|
|
codec = webrtc.NewRTPVP8CodecExt(payloadType, payloadCodec.ClockRate, e.feedbackTypes, payloadCodec.Fmtp)
|
|
case strings.EqualFold(payloadCodec.Name, webrtc.VP9):
|
|
codec = webrtc.NewRTPVP9CodecExt(payloadType, payloadCodec.ClockRate, e.feedbackTypes, payloadCodec.Fmtp)
|
|
case strings.EqualFold(payloadCodec.Name, webrtc.H264):
|
|
codec = webrtc.NewRTPH264CodecExt(payloadType, payloadCodec.ClockRate, e.feedbackTypes, payloadCodec.Fmtp)
|
|
default:
|
|
// ignoring other codecs
|
|
continue
|
|
}
|
|
|
|
e.RegisterCodec(codec)
|
|
}
|
|
}
|
|
|
|
// Use defaults for codecs not provided in sdp
|
|
if len(e.GetCodecsByName(webrtc.Opus)) == 0 {
|
|
codec := webrtc.NewRTPOpusCodec(webrtc.DefaultPayloadTypeOpus, 48000)
|
|
e.RegisterCodec(codec)
|
|
}
|
|
|
|
if len(e.GetCodecsByName(webrtc.VP8)) == 0 {
|
|
codec := webrtc.NewRTPVP8CodecExt(webrtc.DefaultPayloadTypeVP8, 90000, e.feedbackTypes, "")
|
|
e.RegisterCodec(codec)
|
|
}
|
|
|
|
if len(e.GetCodecsByName(webrtc.VP9)) == 0 {
|
|
codec := webrtc.NewRTPVP9CodecExt(webrtc.DefaultPayloadTypeVP9, 90000, e.feedbackTypes, "")
|
|
e.RegisterCodec(codec)
|
|
}
|
|
|
|
if len(e.GetCodecsByName(webrtc.H264)) == 0 {
|
|
codec := webrtc.NewRTPH264CodecExt(webrtc.DefaultPayloadTypeH264, 90000, e.feedbackTypes, "")
|
|
e.RegisterCodec(codec)
|
|
}
|
|
|
|
return nil
|
|
}
|