mirror of
https://github.com/livekit/livekit.git
synced 2026-04-04 12:35:42 +00:00
98 lines
3.2 KiB
Go
98 lines
3.2 KiB
Go
// Copyright 2023 LiveKit, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/pion/interceptor"
|
|
"github.com/pion/rtp"
|
|
"github.com/pion/webrtc/v4"
|
|
|
|
"github.com/livekit/protocol/codecs/mime"
|
|
"github.com/livekit/protocol/livekit"
|
|
)
|
|
|
|
// Do a fuzzy find for a codec in the list of codecs
|
|
// Used for lookup up a codec in an existing list to find a match
|
|
func CodecParametersFuzzySearch(needle webrtc.RTPCodecParameters, haystack []webrtc.RTPCodecParameters) (webrtc.RTPCodecParameters, error) {
|
|
// First attempt to match on MimeType + SDPFmtpLine
|
|
for _, c := range haystack {
|
|
if mime.IsMimeTypeStringEqual(c.RTPCodecCapability.MimeType, needle.RTPCodecCapability.MimeType) &&
|
|
c.RTPCodecCapability.SDPFmtpLine == needle.RTPCodecCapability.SDPFmtpLine {
|
|
return c, nil
|
|
}
|
|
}
|
|
|
|
// Fallback to just MimeType
|
|
for _, c := range haystack {
|
|
if mime.IsMimeTypeStringEqual(c.RTPCodecCapability.MimeType, needle.RTPCodecCapability.MimeType) {
|
|
return c, nil
|
|
}
|
|
}
|
|
|
|
return webrtc.RTPCodecParameters{}, webrtc.ErrCodecNotFound
|
|
}
|
|
|
|
// Given a CodecParameters find the RTX CodecParameters if one exists
|
|
func FindRTXPayloadType(needle webrtc.PayloadType, haystack []webrtc.RTPCodecParameters) webrtc.PayloadType {
|
|
aptStr := fmt.Sprintf("apt=%d", needle)
|
|
for _, c := range haystack {
|
|
if aptStr == c.SDPFmtpLine {
|
|
return c.PayloadType
|
|
}
|
|
}
|
|
|
|
return webrtc.PayloadType(0)
|
|
}
|
|
|
|
// GetHeaderExtensionID returns the ID of a header extension, or 0 if not found
|
|
func GetHeaderExtensionID(extensions []interceptor.RTPHeaderExtension, extension webrtc.RTPHeaderExtensionCapability) int {
|
|
for _, h := range extensions {
|
|
if extension.URI == h.URI {
|
|
return h.ID
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
var (
|
|
ErrInvalidRTPVersion = errors.New("invalid RTP version")
|
|
ErrRTPPayloadTypeMismatch = errors.New("RTP payload type mismatch")
|
|
ErrRTPSSRCMismatch = errors.New("RTP SSRC mismatch")
|
|
)
|
|
|
|
// ValidateRTPPacket checks for a valid RTP packet and returns an error if fields are incorrect
|
|
func ValidateRTPPacket(pkt *rtp.Packet, expectedPayloadType uint8, expectedSSRC uint32) error {
|
|
if pkt.Version != 2 {
|
|
return fmt.Errorf("%w, expected: 2, actual: %d", ErrInvalidRTPVersion, pkt.Version)
|
|
}
|
|
|
|
if expectedPayloadType != 0 && pkt.PayloadType != expectedPayloadType {
|
|
return fmt.Errorf("%w, expected: %d, actual: %d", ErrRTPPayloadTypeMismatch, expectedPayloadType, pkt.PayloadType)
|
|
}
|
|
|
|
if expectedSSRC != 0 && pkt.SSRC != expectedSSRC {
|
|
return fmt.Errorf("%w, expected: %d, actual: %d", ErrRTPSSRCMismatch, expectedSSRC, pkt.SSRC)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func IsSimulcastMode(m livekit.VideoLayer_Mode) bool {
|
|
return m == livekit.VideoLayer_ONE_SPATIAL_LAYER_PER_STREAM || m == livekit.VideoLayer_ONE_SPATIAL_LAYER_PER_STREAM_INCOMPLETE_RTCP_SR
|
|
}
|