github.com/pion/webrtc/v4@v4.0.1/rtpcodec.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  package webrtc
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/pion/webrtc/v4/internal/fmtp"
    11  )
    12  
    13  // RTPCodecType determines the type of a codec
    14  type RTPCodecType int
    15  
    16  const (
    17  	// RTPCodecTypeUnknown is the enum's zero-value
    18  	RTPCodecTypeUnknown RTPCodecType = iota
    19  
    20  	// RTPCodecTypeAudio indicates this is an audio codec
    21  	RTPCodecTypeAudio
    22  
    23  	// RTPCodecTypeVideo indicates this is a video codec
    24  	RTPCodecTypeVideo
    25  )
    26  
    27  func (t RTPCodecType) String() string {
    28  	switch t {
    29  	case RTPCodecTypeAudio:
    30  		return "audio" //nolint: goconst
    31  	case RTPCodecTypeVideo:
    32  		return "video" //nolint: goconst
    33  	default:
    34  		return ErrUnknownType.Error()
    35  	}
    36  }
    37  
    38  // NewRTPCodecType creates a RTPCodecType from a string
    39  func NewRTPCodecType(r string) RTPCodecType {
    40  	switch {
    41  	case strings.EqualFold(r, RTPCodecTypeAudio.String()):
    42  		return RTPCodecTypeAudio
    43  	case strings.EqualFold(r, RTPCodecTypeVideo.String()):
    44  		return RTPCodecTypeVideo
    45  	default:
    46  		return RTPCodecType(0)
    47  	}
    48  }
    49  
    50  // RTPCodecCapability provides information about codec capabilities.
    51  //
    52  // https://w3c.github.io/webrtc-pc/#dictionary-rtcrtpcodeccapability-members
    53  type RTPCodecCapability struct {
    54  	MimeType     string
    55  	ClockRate    uint32
    56  	Channels     uint16
    57  	SDPFmtpLine  string
    58  	RTCPFeedback []RTCPFeedback
    59  }
    60  
    61  // RTPHeaderExtensionCapability is used to define a RFC5285 RTP header extension supported by the codec.
    62  //
    63  // https://w3c.github.io/webrtc-pc/#dom-rtcrtpcapabilities-headerextensions
    64  type RTPHeaderExtensionCapability struct {
    65  	URI string
    66  }
    67  
    68  // RTPHeaderExtensionParameter represents a negotiated RFC5285 RTP header extension.
    69  //
    70  // https://w3c.github.io/webrtc-pc/#dictionary-rtcrtpheaderextensionparameters-members
    71  type RTPHeaderExtensionParameter struct {
    72  	URI string
    73  	ID  int
    74  }
    75  
    76  // RTPCodecParameters is a sequence containing the media codecs that an RtpSender
    77  // will choose from, as well as entries for RTX, RED and FEC mechanisms. This also
    78  // includes the PayloadType that has been negotiated
    79  //
    80  // https://w3c.github.io/webrtc-pc/#rtcrtpcodecparameters
    81  type RTPCodecParameters struct {
    82  	RTPCodecCapability
    83  	PayloadType PayloadType
    84  
    85  	statsID string
    86  }
    87  
    88  // RTPParameters is a list of negotiated codecs and header extensions
    89  //
    90  // https://w3c.github.io/webrtc-pc/#dictionary-rtcrtpparameters-members
    91  type RTPParameters struct {
    92  	HeaderExtensions []RTPHeaderExtensionParameter
    93  	Codecs           []RTPCodecParameters
    94  }
    95  
    96  type codecMatchType int
    97  
    98  const (
    99  	codecMatchNone    codecMatchType = 0
   100  	codecMatchPartial codecMatchType = 1
   101  	codecMatchExact   codecMatchType = 2
   102  )
   103  
   104  // Do a fuzzy find for a codec in the list of codecs
   105  // Used for lookup up a codec in an existing list to find a match
   106  // Returns codecMatchExact, codecMatchPartial, or codecMatchNone
   107  func codecParametersFuzzySearch(needle RTPCodecParameters, haystack []RTPCodecParameters) (RTPCodecParameters, codecMatchType) {
   108  	needleFmtp := fmtp.Parse(needle.RTPCodecCapability.MimeType, needle.RTPCodecCapability.SDPFmtpLine)
   109  
   110  	// First attempt to match on MimeType + SDPFmtpLine
   111  	for _, c := range haystack {
   112  		cfmtp := fmtp.Parse(c.RTPCodecCapability.MimeType, c.RTPCodecCapability.SDPFmtpLine)
   113  		if needleFmtp.Match(cfmtp) {
   114  			return c, codecMatchExact
   115  		}
   116  	}
   117  
   118  	// Fallback to just MimeType
   119  	for _, c := range haystack {
   120  		if strings.EqualFold(c.RTPCodecCapability.MimeType, needle.RTPCodecCapability.MimeType) {
   121  			return c, codecMatchPartial
   122  		}
   123  	}
   124  
   125  	return RTPCodecParameters{}, codecMatchNone
   126  }
   127  
   128  // Given a CodecParameters find the RTX CodecParameters if one exists
   129  func findRTXPayloadType(needle PayloadType, haystack []RTPCodecParameters) PayloadType {
   130  	aptStr := fmt.Sprintf("apt=%d", needle)
   131  	for _, c := range haystack {
   132  		if aptStr == c.SDPFmtpLine {
   133  			return c.PayloadType
   134  		}
   135  	}
   136  
   137  	return PayloadType(0)
   138  }