From eaec24056d064da01f1ab0038dee338313e19e75 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Sun, 19 May 2024 19:45:41 +0200 Subject: [PATCH] Fix codec matching in case of multiple sample rates or channel count --- e2e/e2e_test.go | 2 +- .../bandwidth-estimation-from-disk/main.go | 2 +- examples/insertable-streams/main.go | 2 +- examples/play-from-disk-renegotiation/main.go | 2 +- examples/play-from-disk/main.go | 4 +- examples/reflect/main.go | 2 +- examples/rtp-forwarder/main.go | 2 +- examples/rtp-to-webrtc/main.go | 2 +- examples/save-to-disk/main.go | 2 +- examples/simulcast/main.go | 6 +- examples/swap-tracks/main.go | 2 +- interceptor_test.go | 4 +- internal/fmtp/fmtp.go | 24 ++++- internal/fmtp/fmtp_test.go | 97 +++++++++++++++++-- mediaengine.go | 22 ++++- ortc_media_test.go | 2 +- peerconnection_go_test.go | 2 +- peerconnection_media_test.go | 61 ++++++------ peerconnection_renegotiation_test.go | 40 ++++---- rtpcodec.go | 21 +++- rtpreceiver_go_test.go | 2 +- rtpreceiver_test.go | 2 +- rtpsender_test.go | 46 ++++----- sdpsemantics_test.go | 16 +-- stats_go_test.go | 2 +- track_local_static_test.go | 20 ++-- 26 files changed, 263 insertions(+), 126 deletions(-) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 0e8ca40c3cb..8e0f65686ba 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -337,7 +337,7 @@ func createTrack(offer webrtc.SessionDescription) (*webrtc.PeerConnection, *webr return nil, nil, nil, errPc } - track, errTrack := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus}, "audio", "pion") + track, errTrack := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 2}, "audio", "pion") if errTrack != nil { return nil, nil, nil, errTrack } diff --git a/examples/bandwidth-estimation-from-disk/main.go b/examples/bandwidth-estimation-from-disk/main.go index 79797ef7e00..450815cc6ec 100644 --- a/examples/bandwidth-estimation-from-disk/main.go +++ b/examples/bandwidth-estimation-from-disk/main.go @@ -108,7 +108,7 @@ func main() { estimator := <-estimatorChan // Create a video track - videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion") + videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video", "pion") if err != nil { panic(err) } diff --git a/examples/insertable-streams/main.go b/examples/insertable-streams/main.go index 831e35851f7..427422c9877 100644 --- a/examples/insertable-streams/main.go +++ b/examples/insertable-streams/main.go @@ -42,7 +42,7 @@ func main() { }() // Create a video track - videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion") + videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video", "pion") if err != nil { panic(err) } diff --git a/examples/play-from-disk-renegotiation/main.go b/examples/play-from-disk-renegotiation/main.go index de4b2d6d027..66ccc80e641 100644 --- a/examples/play-from-disk-renegotiation/main.go +++ b/examples/play-from-disk-renegotiation/main.go @@ -74,7 +74,7 @@ func createPeerConnection(w http.ResponseWriter, r *http.Request) { // Add a single video track func addVideo(w http.ResponseWriter, r *http.Request) { videoTrack, err := webrtc.NewTrackLocalStaticSample( - webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, + webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, fmt.Sprintf("video-%d", randutil.NewMathRandomGenerator().Uint32()), fmt.Sprintf("video-%d", randutil.NewMathRandomGenerator().Uint32()), ) diff --git a/examples/play-from-disk/main.go b/examples/play-from-disk/main.go index 7486bd69e47..f25a23b1667 100644 --- a/examples/play-from-disk/main.go +++ b/examples/play-from-disk/main.go @@ -85,7 +85,7 @@ func main() { } // Create a video track - videoTrack, videoTrackErr := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: trackCodec}, "video", "pion") + videoTrack, videoTrackErr := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: trackCodec, ClockRate: 90000}, "video", "pion") if videoTrackErr != nil { panic(videoTrackErr) } @@ -149,7 +149,7 @@ func main() { if haveAudioFile { // Create a audio track - audioTrack, audioTrackErr := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus}, "audio", "pion") + audioTrack, audioTrackErr := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 2}, "audio", "pion") if audioTrackErr != nil { panic(audioTrackErr) } diff --git a/examples/reflect/main.go b/examples/reflect/main.go index 2b0244ec688..a6794fa80c8 100644 --- a/examples/reflect/main.go +++ b/examples/reflect/main.go @@ -77,7 +77,7 @@ func main() { }() // Create Track that we send video back to browser on - outputTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion") + outputTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video", "pion") if err != nil { panic(err) } diff --git a/examples/rtp-forwarder/main.go b/examples/rtp-forwarder/main.go index b92b931b9d4..d5b22556ee6 100644 --- a/examples/rtp-forwarder/main.go +++ b/examples/rtp-forwarder/main.go @@ -41,7 +41,7 @@ func main() { panic(err) } if err := m.RegisterCodec(webrtc.RTPCodecParameters{ - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil}, + RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 2, SDPFmtpLine: "", RTCPFeedback: nil}, }, webrtc.RTPCodecTypeAudio); err != nil { panic(err) } diff --git a/examples/rtp-to-webrtc/main.go b/examples/rtp-to-webrtc/main.go index b36f258783a..19a41ab6683 100644 --- a/examples/rtp-to-webrtc/main.go +++ b/examples/rtp-to-webrtc/main.go @@ -50,7 +50,7 @@ func main() { }() // Create a video track - videoTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion") + videoTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video", "pion") if err != nil { panic(err) } diff --git a/examples/save-to-disk/main.go b/examples/save-to-disk/main.go index 4568e23ebf4..250a347b247 100644 --- a/examples/save-to-disk/main.go +++ b/examples/save-to-disk/main.go @@ -55,7 +55,7 @@ func main() { panic(err) } if err := m.RegisterCodec(webrtc.RTPCodecParameters{ - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil}, + RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 2, SDPFmtpLine: "", RTCPFeedback: nil}, PayloadType: 111, }, webrtc.RTPCodecTypeAudio); err != nil { panic(err) diff --git a/examples/simulcast/main.go b/examples/simulcast/main.go index 3a0d9e881c8..25a9f42a402 100644 --- a/examples/simulcast/main.go +++ b/examples/simulcast/main.go @@ -73,19 +73,19 @@ func main() { outputTracks := map[string]*webrtc.TrackLocalStaticRTP{} // Create Track that we send video back to browser on - outputTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video_q", "pion_q") + outputTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video_q", "pion_q") if err != nil { panic(err) } outputTracks["q"] = outputTrack - outputTrack, err = webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video_h", "pion_h") + outputTrack, err = webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video_h", "pion_h") if err != nil { panic(err) } outputTracks["h"] = outputTrack - outputTrack, err = webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video_f", "pion_f") + outputTrack, err = webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video_f", "pion_f") if err != nil { panic(err) } diff --git a/examples/swap-tracks/main.go b/examples/swap-tracks/main.go index 02ffc8399db..e42d9d7f57d 100644 --- a/examples/swap-tracks/main.go +++ b/examples/swap-tracks/main.go @@ -43,7 +43,7 @@ func main() { // nolint:gocognit }() // Create Track that we send video back to browser on - outputTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8}, "video", "pion") + outputTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, "video", "pion") if err != nil { panic(err) } diff --git a/interceptor_test.go b/interceptor_test.go index 7b50da027dc..149576c406f 100644 --- a/interceptor_test.go +++ b/interceptor_test.go @@ -73,7 +73,7 @@ func TestPeerConnection_Interceptor(t *testing.T) { offerer := createPC() answerer := createPC() - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = offerer.AddTrack(track) @@ -163,7 +163,7 @@ func Test_Interceptor_BindUnbind(t *testing.T) { sender, receiver, err := NewAPI(WithMediaEngine(m), WithInterceptorRegistry(ir)).newPair(Configuration{}) assert.NoError(t, err) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = sender.AddTrack(track) diff --git a/internal/fmtp/fmtp.go b/internal/fmtp/fmtp.go index f515a648d01..ea63458a26c 100644 --- a/internal/fmtp/fmtp.go +++ b/internal/fmtp/fmtp.go @@ -24,6 +24,16 @@ func parseParameters(line string) map[string]string { return parameters } +func channelsEqual(a, b uint16) bool { + if a == 0 { + a = 1 + } + if b == 0 { + b = 1 + } + return a == b +} + // FMTP interface for implementing custom // FMTP parsers based on MimeType type FMTP interface { @@ -39,7 +49,7 @@ type FMTP interface { } // Parse parses an fmtp string based on the MimeType -func Parse(mimeType, line string) FMTP { +func Parse(mimeType string, clockRate uint32, channels uint16, line string) FMTP { var f FMTP parameters := parseParameters(line) @@ -63,6 +73,8 @@ func Parse(mimeType, line string) FMTP { default: f = &genericFMTP{ mimeType: mimeType, + clockRate: clockRate, + channels: channels, parameters: parameters, } } @@ -72,6 +84,8 @@ func Parse(mimeType, line string) FMTP { type genericFMTP struct { mimeType string + clockRate uint32 + channels uint16 parameters map[string]string } @@ -91,6 +105,14 @@ func (g *genericFMTP) Match(b FMTP) bool { return false } + if g.clockRate != c.clockRate { + return false + } + + if !channelsEqual(g.channels, c.channels) { + return false + } + for k, v := range g.parameters { if vb, ok := c.parameters[k]; ok && !strings.EqualFold(vb, v) { return false diff --git a/internal/fmtp/fmtp_test.go b/internal/fmtp/fmtp_test.go index 96c1a8e7434..6702bbeb304 100644 --- a/internal/fmtp/fmtp_test.go +++ b/internal/fmtp/fmtp_test.go @@ -56,17 +56,23 @@ func TestParseParameters(t *testing.T) { func TestParse(t *testing.T) { for _, ca := range []struct { - name string - mimeType string - line string - expected FMTP + name string + mimeType string + clockRate uint32 + channels uint16 + line string + expected FMTP }{ { "generic", "generic", + 90000, + 2, "key-name=value", &genericFMTP{ - mimeType: "generic", + mimeType: "generic", + clockRate: 90000, + channels: 2, parameters: map[string]string{ "key-name": "value", }, @@ -75,9 +81,13 @@ func TestParse(t *testing.T) { { "generic case normalization", "generic", + 90000, + 2, "Key=value", &genericFMTP{ - mimeType: "generic", + mimeType: "generic", + clockRate: 90000, + channels: 2, parameters: map[string]string{ "key": "value", }, @@ -86,6 +96,8 @@ func TestParse(t *testing.T) { { "h264", "video/h264", + 90000, + 0, "key-name=value", &h264FMTP{ parameters: map[string]string{ @@ -96,6 +108,8 @@ func TestParse(t *testing.T) { { "vp9", "video/vp9", + 90000, + 0, "key-name=value", &vp9FMTP{ parameters: map[string]string{ @@ -106,6 +120,8 @@ func TestParse(t *testing.T) { { "av1", "video/av1", + 90000, + 0, "key-name=value", &av1FMTP{ parameters: map[string]string{ @@ -115,7 +131,7 @@ func TestParse(t *testing.T) { }, } { t.Run(ca.name, func(t *testing.T) { - f := Parse(ca.mimeType, ca.line) + f := Parse(ca.mimeType, ca.clockRate, ca.channels, ca.line) if !reflect.DeepEqual(ca.expected, f) { t.Errorf("expected '%v', got '%v'", ca.expected, f) } @@ -177,6 +193,27 @@ func TestMatch(t *testing.T) { }, true, }, + { + "generic inferred channels", + &genericFMTP{ + mimeType: "generic", + channels: 1, + parameters: map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + &genericFMTP{ + mimeType: "generic", + parameters: map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + true, + }, { "generic inconsistent different kind", &genericFMTP{ @@ -210,6 +247,52 @@ func TestMatch(t *testing.T) { }, false, }, + { + "generic inconsistent different clock rate", + &genericFMTP{ + mimeType: "generic", + clockRate: 90000, + parameters: map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + &genericFMTP{ + mimeType: "generic", + clockRate: 48000, + parameters: map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + false, + }, + { + "generic inconsistent different channels", + &genericFMTP{ + mimeType: "generic", + clockRate: 90000, + channels: 2, + parameters: map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + &genericFMTP{ + mimeType: "generic", + clockRate: 90000, + channels: 1, + parameters: map[string]string{ + "key1": "value1", + "key2": "value2", + "key3": "value3", + }, + }, + false, + }, { "generic inconsistent different parameters", &genericFMTP{ diff --git a/mediaengine.go b/mediaengine.go index 7abb8c3a798..cc7f0d7df0a 100644 --- a/mediaengine.go +++ b/mediaengine.go @@ -49,6 +49,16 @@ const ( MimeTypePCMA = "audio/PCMA" ) +func channelsEqual(a, b uint16) bool { + if a == 0 { + a = 1 + } + if b == 0 { + b = 1 + } + return a == b +} + type mediaEngineHeaderExtension struct { uri string isAudio, isVideo bool @@ -211,7 +221,10 @@ func (m *MediaEngine) RegisterDefaultCodecs() error { // addCodec will append codec if it not exists func (m *MediaEngine) addCodec(codecs []RTPCodecParameters, codec RTPCodecParameters) []RTPCodecParameters { for _, c := range codecs { - if c.MimeType == codec.MimeType && c.PayloadType == codec.PayloadType { + if c.MimeType == codec.MimeType && + c.ClockRate == codec.ClockRate && + channelsEqual(c.Channels, codec.Channels) && + c.PayloadType == codec.PayloadType { return codecs } } @@ -407,7 +420,12 @@ func (m *MediaEngine) matchRemoteCodec(remoteCodec RTPCodecParameters, typ RTPCo codecs = m.audioCodecs } - remoteFmtp := fmtp.Parse(remoteCodec.RTPCodecCapability.MimeType, remoteCodec.RTPCodecCapability.SDPFmtpLine) + remoteFmtp := fmtp.Parse( + remoteCodec.RTPCodecCapability.MimeType, + remoteCodec.RTPCodecCapability.ClockRate, + remoteCodec.RTPCodecCapability.Channels, + remoteCodec.RTPCodecCapability.SDPFmtpLine) + if apt, hasApt := remoteFmtp.Parameter("apt"); hasApt { payloadType, err := strconv.ParseUint(apt, 10, 8) if err != nil { diff --git a/ortc_media_test.go b/ortc_media_test.go index 966d285cc06..ff3766ba01e 100644 --- a/ortc_media_test.go +++ b/ortc_media_test.go @@ -31,7 +31,7 @@ func Test_ORTC_Media(t *testing.T) { assert.NoError(t, signalORTCPair(stackA, stackB)) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) rtpSender, err := stackA.api.NewRTPSender(track, stackA.dtls) diff --git a/peerconnection_go_test.go b/peerconnection_go_test.go index b51a0c65057..383af43f9b9 100644 --- a/peerconnection_go_test.go +++ b/peerconnection_go_test.go @@ -1024,7 +1024,7 @@ type trackRecords struct { func (r *trackRecords) newTrack() (*TrackLocalStaticRTP, error) { trackID := fmt.Sprintf("pion-track-%d", len(r.trackIDs)) - track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, trackID, "pion") + track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, trackID, "pion") r.trackIDs[trackID] = struct{}{} return track, err } diff --git a/peerconnection_media_test.go b/peerconnection_media_test.go index 0ef49e48c9d..7b77421cd5b 100644 --- a/peerconnection_media_test.go +++ b/peerconnection_media_test.go @@ -138,7 +138,7 @@ func TestPeerConnection_Media_Sample(t *testing.T) { } }) - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, expectedTrackID, expectedStreamID) + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, expectedTrackID, expectedStreamID) if err != nil { t.Fatal(err) } @@ -245,12 +245,12 @@ func TestPeerConnection_Media_Shutdown(t *testing.T) { t.Fatal(err) } - opusTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus}, "audio", "pion1") + opusTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 48000, Channels: 2}, "audio", "pion1") if err != nil { t.Fatal(err) } - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") if err != nil { t.Fatal(err) } @@ -338,7 +338,7 @@ func TestPeerConnection_Media_Disconnected(t *testing.T) { t.Fatal(err) } - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") if err != nil { t.Fatal(err) } @@ -440,7 +440,7 @@ func TestUndeclaredSSRC(t *testing.T) { pcOffer, pcAnswer, err := newPair() assert.NoError(t, err) - vp8Writer, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + vp8Writer, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") assert.NoError(t, err) _, err = pcOffer.AddTrack(vp8Writer) @@ -487,7 +487,7 @@ func TestUndeclaredSSRC(t *testing.T) { }), WithMediaEngine(m)).newPair(Configuration{}) assert.NoError(t, err) - vp8Writer, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + vp8Writer, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") assert.NoError(t, err) _, err = pcOffer.AddTrack(vp8Writer) @@ -531,7 +531,7 @@ func TestAddTransceiverFromTrackSendOnly(t *testing.T) { } track, err := NewTrackLocalStaticSample( - RTPCodecCapability{MimeType: "audio/Opus"}, + RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 48000, Channels: 2}, "track-id", "stream-id", ) @@ -587,7 +587,7 @@ func TestAddTransceiverFromTrackSendRecv(t *testing.T) { } track, err := NewTrackLocalStaticSample( - RTPCodecCapability{MimeType: "audio/Opus"}, + RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 48000, Channels: 2}, "track-id", "stream-id", ) @@ -638,7 +638,7 @@ func TestAddTransceiverAddTrack_Reuse(t *testing.T) { assert.Equal(t, []*RTPTransceiver{tr}, pc.GetTransceivers()) addTrack := func() (TrackLocal, *RTPSender) { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) sender, err := pc.AddTrack(track) @@ -676,7 +676,7 @@ func TestAddTransceiverAddTrack_NewRTPSender_Error(t *testing.T) { dtlsTransport := pc.dtlsTransport pc.dtlsTransport = nil - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) _, err = pc.AddTrack(track) @@ -762,7 +762,10 @@ func TestAddTransceiverFromTrackFailsRecvOnly(t *testing.T) { } track, err := NewTrackLocalStaticSample( - RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, + RTPCodecCapability{ + MimeType: MimeTypeH264, + ClockRate: 90000, + SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "track-id", "track-label", ) @@ -785,7 +788,7 @@ func TestAddTransceiverFromTrackFailsRecvOnly(t *testing.T) { func TestPlanBMediaExchange(t *testing.T) { runTest := func(trackCount int, t *testing.T) { addSingleTrack := func(p *PeerConnection) *TrackLocalStaticSample { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, fmt.Sprintf("video-%d", randutil.NewMathRandomGenerator().Uint32()), fmt.Sprintf("video-%d", randutil.NewMathRandomGenerator().Uint32())) + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, fmt.Sprintf("video-%d", randutil.NewMathRandomGenerator().Uint32()), fmt.Sprintf("video-%d", randutil.NewMathRandomGenerator().Uint32())) assert.NoError(t, err) _, err = p.AddTrack(track) @@ -870,7 +873,7 @@ func TestPeerConnection_Start_Only_Negotiated_Senders(t *testing.T) { assert.NoError(t, err) defer func() { assert.NoError(t, pcAnswer.Close()) }() - track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion1") + track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion1") require.NoError(t, err) sender1, err := pcOffer.AddTrack(track1) @@ -891,7 +894,7 @@ func TestPeerConnection_Start_Only_Negotiated_Senders(t *testing.T) { // Add a new track between providing the offer and applying the answer - track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") require.NoError(t, err) sender2, err := pcOffer.AddTrack(track2) @@ -934,7 +937,7 @@ func TestPeerConnection_Start_Right_Receiver(t *testing.T) { _, err = pcAnswer.AddTransceiverFromKind(RTPCodecTypeVideo, RTPTransceiverInit{Direction: RTPTransceiverDirectionRecvonly}) assert.NoError(t, err) - track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion1") + track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion1") require.NoError(t, err) sender1, err := pcOffer.AddTrack(track1) @@ -997,7 +1000,7 @@ func TestPeerConnection_Simulcast_Probe(t *testing.T) { // Assert that failed Simulcast probing doesn't cause // the handleUndeclaredSSRC to be leaked t.Run("Leak", func(t *testing.T) { - track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) offerer, answerer, err := newPair() @@ -1061,13 +1064,13 @@ func TestPeerConnection_Simulcast_Probe(t *testing.T) { }), WithMediaEngine(m)).newPair(Configuration{}) assert.NoError(t, err) - firstTrack, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "firstTrack", "firstTrack") + firstTrack, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "firstTrack", "firstTrack") assert.NoError(t, err) _, err = pcOffer.AddTrack(firstTrack) assert.NoError(t, err) - secondTrack, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "secondTrack", "secondTrack") + secondTrack, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "secondTrack", "secondTrack") assert.NoError(t, err) _, err = pcOffer.AddTrack(secondTrack) @@ -1157,7 +1160,7 @@ func TestPeerConnection_CreateOffer_NoCodecs(t *testing.T) { pc, err := NewAPI(WithMediaEngine(m)).NewPeerConnection(Configuration{}) assert.NoError(t, err) - track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = pc.AddTrack(track) @@ -1175,7 +1178,7 @@ func TestPeerConnection_RaceReplaceTrack(t *testing.T) { assert.NoError(t, err) addTrack := func() *TrackLocalStaticSample { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) _, err = pc.AddTrack(track) assert.NoError(t, err) @@ -1263,19 +1266,19 @@ func TestPeerConnection_Simulcast(t *testing.T) { pcOffer, pcAnswer, err := NewAPI(WithMediaEngine(m)).newPair(Configuration{}) assert.NoError(t, err) - vp8WriterA, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2", WithRTPStreamID("a")) + vp8WriterA, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2", WithRTPStreamID("a")) assert.NoError(t, err) sender, err := pcOffer.AddTrack(vp8WriterA) assert.NoError(t, err) assert.NotNil(t, sender) - vp8WriterB, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2", WithRTPStreamID("b")) + vp8WriterB, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2", WithRTPStreamID("b")) assert.NoError(t, err) err = sender.AddEncoding(vp8WriterB) assert.NoError(t, err) - vp8WriterC, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2", WithRTPStreamID("c")) + vp8WriterC, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2", WithRTPStreamID("c")) assert.NoError(t, err) err = sender.AddEncoding(vp8WriterC) assert.NoError(t, err) @@ -1419,10 +1422,10 @@ func TestPeerConnection_Simulcast_RTX(t *testing.T) { rids := []string{"a", "b"} - vp8WriterAStatic, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2", WithRTPStreamID(rids[0])) + vp8WriterAStatic, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2", WithRTPStreamID(rids[0])) require.NoError(t, err) - vp8WriterBStatic, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2", WithRTPStreamID(rids[1])) + vp8WriterBStatic, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2", WithRTPStreamID(rids[1])) require.NoError(t, err) vp8WriterA, vp8WriterB := &simulcastTestTrackLocal{vp8WriterAStatic}, &simulcastTestTrackLocal{vp8WriterBStatic} @@ -1645,19 +1648,19 @@ func TestPeerConnection_Simulcast_NoDataChannel(t *testing.T) { go func() { defer wg.Done() - vp8WriterA, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("a")) + vp8WriterA, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("a")) assert.NoError(t, err) sender, err := pcSender.AddTrack(vp8WriterA) assert.NoError(t, err) assert.NotNil(t, sender) - vp8WriterB, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("b")) + vp8WriterB, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("b")) assert.NoError(t, err) err = sender.AddEncoding(vp8WriterB) assert.NoError(t, err) - vp8WriterC, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("c")) + vp8WriterC, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("c")) assert.NoError(t, err) err = sender.AddEncoding(vp8WriterC) assert.NoError(t, err) @@ -1743,7 +1746,7 @@ func TestPeerConnection_Zero_PayloadType(t *testing.T) { pcOffer, pcAnswer, err := newPair() require.NoError(t, err) - audioTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypePCMU}, "audio", "audio") + audioTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypePCMU, ClockRate: 8000}, "audio", "audio") require.NoError(t, err) _, err = pcOffer.AddTrack(audioTrack) diff --git a/peerconnection_renegotiation_test.go b/peerconnection_renegotiation_test.go index fd8967c31e9..1cf68fd852f 100644 --- a/peerconnection_renegotiation_test.go +++ b/peerconnection_renegotiation_test.go @@ -113,7 +113,7 @@ func TestPeerConnection_Renegotiation_AddRecvonlyTransceiver(t *testing.T) { assert.NoError(t, signalPair(pcOffer, pcAnswer)) localTrack, err := NewTrackLocalStaticSample( - RTPCodecCapability{MimeType: "video/VP8"}, "track-one", "stream-one", + RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "track-one", "stream-one", ) require.NoError(t, err) @@ -178,7 +178,7 @@ func TestPeerConnection_Renegotiation_AddTrack(t *testing.T) { _, err = pcAnswer.AddTransceiverFromKind(RTPCodecTypeVideo, RTPTransceiverInit{Direction: RTPTransceiverDirectionRecvonly}) assert.NoError(t, err) - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) sender, err := pcOffer.AddTrack(vp8Track) @@ -221,7 +221,7 @@ func TestPeerConnection_Renegotiation_AddTrack_Multiple(t *testing.T) { _, err := pcAnswer.AddTransceiverFromKind(RTPCodecTypeVideo, RTPTransceiverInit{Direction: RTPTransceiverDirectionRecvonly}) assert.NoError(t, err) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, trackID, trackID) + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, trackID, trackID) assert.NoError(t, err) _, err = pcOffer.AddTrack(track) @@ -298,7 +298,7 @@ func TestPeerConnection_Renegotiation_AddTrack_Rename(t *testing.T) { _, err = pcOffer.AddTransceiverFromKind(RTPCodecTypeVideo, RTPTransceiverInit{Direction: RTPTransceiverDirectionRecvonly}) assert.NoError(t, err) - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo1", "bar1") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo1", "bar1") assert.NoError(t, err) _, err = pcAnswer.AddTrack(vp8Track) assert.NoError(t, err) @@ -337,13 +337,13 @@ func TestPeerConnection_Transceiver_Mid(t *testing.T) { pcAnswer, err := NewPeerConnection(Configuration{}) assert.NoError(t, err) - track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion1") + track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion1") require.NoError(t, err) sender1, err := pcOffer.AddTrack(track1) require.NoError(t, err) - track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") require.NoError(t, err) sender2, err := pcOffer.AddTrack(track2) @@ -400,7 +400,7 @@ func TestPeerConnection_Transceiver_Mid(t *testing.T) { assert.NoError(t, err) assert.NoError(t, pcOffer.SetRemoteDescription(answer)) - track3, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion3") + track3, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion3") require.NoError(t, err) sender3, err := pcOffer.AddTrack(track3) @@ -431,10 +431,10 @@ func TestPeerConnection_Renegotiation_CodecChange(t *testing.T) { pcAnswer, err := NewPeerConnection(Configuration{}) assert.NoError(t, err) - track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video1", "pion1") + track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video1", "pion1") require.NoError(t, err) - track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video2", "pion2") + track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video2", "pion2") require.NoError(t, err) sender1, err := pcOffer.AddTrack(track1) @@ -524,7 +524,7 @@ func TestPeerConnection_Renegotiation_RemoveTrack(t *testing.T) { _, err = pcAnswer.AddTransceiverFromKind(RTPCodecTypeVideo, RTPTransceiverInit{Direction: RTPTransceiverDirectionRecvonly}) assert.NoError(t, err) - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) sender, err := pcOffer.AddTrack(vp8Track) @@ -578,7 +578,7 @@ func TestPeerConnection_RoleSwitch(t *testing.T) { _, err = pcFirstOfferer.AddTransceiverFromKind(RTPCodecTypeVideo, RTPTransceiverInit{Direction: RTPTransceiverDirectionRecvonly}) assert.NoError(t, err) - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) _, err = pcSecondOfferer.AddTrack(vp8Track) @@ -685,7 +685,7 @@ func TestPeerConnection_Renegotiation_SetLocalDescription(t *testing.T) { _, err = pcOffer.AddTransceiverFromKind(RTPCodecTypeVideo, RTPTransceiverInit{Direction: RTPTransceiverDirectionRecvonly}) assert.NoError(t, err) - localTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + localTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) sender, err := pcAnswer.AddTrack(localTrack) @@ -798,7 +798,7 @@ func TestAddDataChannelDuringRenegotiation(t *testing.T) { pcAnswer, err := NewPeerConnection(Configuration{}) assert.NoError(t, err) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = pcOffer.AddTrack(track) @@ -890,7 +890,7 @@ func TestNegotiationNeededRemoveTrack(t *testing.T) { pcAnswer, err := NewPeerConnection(Configuration{}) assert.NoError(t, err) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) pcOffer.OnNegotiationNeeded(func() { @@ -952,7 +952,7 @@ func TestNegotiationNeededStressOneSided(t *testing.T) { }) for i := 0; i < expectedTrackCount; i++ { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = pcA.AddTrack(track) @@ -1084,7 +1084,7 @@ func TestPeerConnection_Renegotiation_Simulcast(t *testing.T) { pcOffer, pcAnswer, err := NewAPI(WithMediaEngine(m)).newPair(Configuration{}) assert.NoError(t, err) - vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") assert.NoError(t, err) rtpTransceiver, err := pcOffer.AddTransceiverFromTrack( @@ -1117,7 +1117,7 @@ func TestPeerConnection_Renegotiation_Simulcast(t *testing.T) { pcOffer, pcAnswer, err := NewAPI(WithMediaEngine(m)).newPair(Configuration{}) assert.NoError(t, err) - vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion2") + vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion2") assert.NoError(t, err) _, err = pcOffer.AddTransceiverFromTrack( @@ -1167,7 +1167,7 @@ func TestPeerConnection_Regegotiation_ReuseTransceiver(t *testing.T) { t.Fatal(err) } - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) sender, err := pcOffer.AddTrack(vp8Track) assert.NoError(t, err) @@ -1179,7 +1179,7 @@ func TestPeerConnection_Regegotiation_ReuseTransceiver(t *testing.T) { assert.Equal(t, pcOffer.GetTransceivers()[0].getCurrentDirection(), RTPTransceiverDirectionSendonly) // should not reuse tranceiver - vp8Track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + vp8Track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) sender2, err := pcOffer.AddTrack(vp8Track2) assert.NoError(t, err) @@ -1259,7 +1259,7 @@ func TestPeerConnection_Regegotiation_AnswerAddsTrack(t *testing.T) { } }) - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "foo", "bar") assert.NoError(t, err) assert.NoError(t, signalPair(pcOffer, pcAnswer)) diff --git a/rtpcodec.go b/rtpcodec.go index 4b8f81c4e74..ade5da52cbb 100644 --- a/rtpcodec.go +++ b/rtpcodec.go @@ -102,19 +102,30 @@ const ( // Used for lookup up a codec in an existing list to find a match // Returns codecMatchExact, codecMatchPartial, or codecMatchNone func codecParametersFuzzySearch(needle RTPCodecParameters, haystack []RTPCodecParameters) (RTPCodecParameters, codecMatchType) { - needleFmtp := fmtp.Parse(needle.RTPCodecCapability.MimeType, needle.RTPCodecCapability.SDPFmtpLine) + needleFmtp := fmtp.Parse( + needle.RTPCodecCapability.MimeType, + needle.RTPCodecCapability.ClockRate, + needle.RTPCodecCapability.Channels, + needle.RTPCodecCapability.SDPFmtpLine) - // First attempt to match on MimeType + SDPFmtpLine + // First attempt to match on MimeType + Channels + SDPFmtpLine for _, c := range haystack { - cfmtp := fmtp.Parse(c.RTPCodecCapability.MimeType, c.RTPCodecCapability.SDPFmtpLine) + cfmtp := fmtp.Parse( + c.RTPCodecCapability.MimeType, + c.RTPCodecCapability.ClockRate, + c.RTPCodecCapability.Channels, + c.RTPCodecCapability.SDPFmtpLine) + if needleFmtp.Match(cfmtp) { return c, codecMatchExact } } - // Fallback to just MimeType + // Fallback to just MimeType + Channels for _, c := range haystack { - if strings.EqualFold(c.RTPCodecCapability.MimeType, needle.RTPCodecCapability.MimeType) { + if strings.EqualFold(c.RTPCodecCapability.MimeType, needle.RTPCodecCapability.MimeType) && + c.RTPCodecCapability.ClockRate == needle.RTPCodecCapability.ClockRate && + channelsEqual(c.RTPCodecCapability.Channels, needle.RTPCodecCapability.Channels) { return c, codecMatchPartial } } diff --git a/rtpreceiver_go_test.go b/rtpreceiver_go_test.go index 47b6982a230..02f944f1018 100644 --- a/rtpreceiver_go_test.go +++ b/rtpreceiver_go_test.go @@ -18,7 +18,7 @@ import ( func TestSetRTPParameters(t *testing.T) { sender, receiver, wan := createVNetPair(t) - outgoingTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + outgoingTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = sender.AddTrack(outgoingTrack) diff --git a/rtpreceiver_test.go b/rtpreceiver_test.go index bda4a0fa784..dbeef0728ee 100644 --- a/rtpreceiver_test.go +++ b/rtpreceiver_test.go @@ -27,7 +27,7 @@ func Test_RTPReceiver_SetReadDeadline(t *testing.T) { sender, receiver, wan := createVNetPair(t) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = sender.AddTrack(track) diff --git a/rtpsender_test.go b/rtpsender_test.go index d071e5a8238..445fc841a55 100644 --- a/rtpsender_test.go +++ b/rtpsender_test.go @@ -35,10 +35,10 @@ func Test_RTPSender_ReplaceTrack(t *testing.T) { sender, receiver, err := NewAPI(WithMediaEngine(m), WithSettingEngine(s)).newPair(Configuration{}) assert.NoError(t, err) - trackA, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + trackA, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) - trackB, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264}, "video", "pion") + trackB, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) rtpSender, err := sender.AddTrack(trackA) @@ -141,7 +141,7 @@ func Test_RTPSender_GetParameters_WithRID(t *testing.T) { assert.NoError(t, signalPair(offerer, answerer)) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("moo")) + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("moo")) assert.NoError(t, err) err = rtpTransceiver.setSendingTrack(track) @@ -162,7 +162,7 @@ func Test_RTPSender_SetReadDeadline(t *testing.T) { sender, receiver, wan := createVNetPair(t) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) rtpSender, err := sender.AddTrack(track) @@ -192,10 +192,10 @@ func Test_RTPSender_ReplaceTrack_InvalidTrackKindChange(t *testing.T) { sender, receiver, err := newPair() assert.NoError(t, err) - trackA, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + trackA, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) - trackB, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus}, "audio", "pion") + trackB, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 90000, Channels: 2}, "audio", "pion") assert.NoError(t, err) rtpSender, err := sender.AddTrack(trackA) @@ -234,17 +234,17 @@ func Test_RTPSender_ReplaceTrack_InvalidCodecChange(t *testing.T) { sender, receiver, err := newPair() assert.NoError(t, err) - trackA, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + trackA, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) - trackB, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP9}, "video", "pion") + trackB, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP9, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) rtpSender, err := sender.AddTrack(trackA) assert.NoError(t, err) err = rtpSender.rtpTransceiver.SetCodecPreferences([]RTPCodecParameters{{ - RTPCodecCapability: RTPCodecCapability{MimeType: MimeTypeVP8}, + RTPCodecCapability: RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, PayloadType: 96, }}) assert.NoError(t, err) @@ -273,7 +273,7 @@ func Test_RTPSender_ReplaceTrack_InvalidCodecChange(t *testing.T) { } func Test_RTPSender_GetParameters_NilTrack(t *testing.T) { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) peerConnection, err := NewPeerConnection(Configuration{}) @@ -289,7 +289,7 @@ func Test_RTPSender_GetParameters_NilTrack(t *testing.T) { } func Test_RTPSender_Send(t *testing.T) { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) peerConnection, err := NewPeerConnection(Configuration{}) @@ -307,7 +307,7 @@ func Test_RTPSender_Send(t *testing.T) { } func Test_RTPSender_Send_Called_Once(t *testing.T) { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) peerConnection, err := NewPeerConnection(Configuration{}) @@ -328,7 +328,7 @@ func Test_RTPSender_Send_Called_Once(t *testing.T) { } func Test_RTPSender_Send_Track_Removed(t *testing.T) { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) peerConnection, err := NewPeerConnection(Configuration{}) @@ -345,7 +345,7 @@ func Test_RTPSender_Send_Track_Removed(t *testing.T) { } func Test_RTPSender_Add_Encoding(t *testing.T) { - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) peerConnection, err := NewPeerConnection(Configuration{}) @@ -356,44 +356,44 @@ func Test_RTPSender_Add_Encoding(t *testing.T) { assert.Equal(t, errRTPSenderTrackNil, rtpSender.AddEncoding(nil)) - track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) assert.Equal(t, errRTPSenderRidNil, rtpSender.AddEncoding(track1)) - track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("h")) + track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("h")) assert.NoError(t, err) assert.Equal(t, errRTPSenderNoBaseEncoding, rtpSender.AddEncoding(track1)) - track, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("q")) + track, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("q")) assert.NoError(t, err) rtpSender, err = peerConnection.AddTrack(track) assert.NoError(t, err) - track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video1", "pion", WithRTPStreamID("h")) + track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video1", "pion", WithRTPStreamID("h")) assert.NoError(t, err) assert.Equal(t, errRTPSenderBaseEncodingMismatch, rtpSender.AddEncoding(track1)) - track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion1", WithRTPStreamID("h")) + track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion1", WithRTPStreamID("h")) assert.NoError(t, err) assert.Equal(t, errRTPSenderBaseEncodingMismatch, rtpSender.AddEncoding(track1)) - track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus}, "video", "pion", WithRTPStreamID("h")) + track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 90000, Channels: 2}, "video", "pion", WithRTPStreamID("h")) assert.NoError(t, err) assert.Equal(t, errRTPSenderBaseEncodingMismatch, rtpSender.AddEncoding(track1)) - track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("q")) + track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("q")) assert.NoError(t, err) assert.Equal(t, errRTPSenderRIDCollision, rtpSender.AddEncoding(track1)) - track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("h")) + track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("h")) assert.NoError(t, err) assert.NoError(t, rtpSender.AddEncoding(track1)) err = rtpSender.Send(rtpSender.GetParameters()) assert.NoError(t, err) - track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion", WithRTPStreamID("f")) + track1, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion", WithRTPStreamID("f")) assert.NoError(t, err) assert.Equal(t, errRTPSenderSendAlreadyCalled, rtpSender.AddEncoding(track1)) diff --git a/sdpsemantics_test.go b/sdpsemantics_test.go index 418a1e8fae1..56f5a13b2d1 100644 --- a/sdpsemantics_test.go +++ b/sdpsemantics_test.go @@ -194,25 +194,25 @@ func TestSDPSemantics_PlanBAnswerSenders(t *testing.T) { }) assert.NoError(t, err) - video1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "1", "1") + video1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "1", "1") assert.NoError(t, err) _, err = apc.AddTrack(video1) assert.NoError(t, err) - video2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "2", "2") + video2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "2", "2") assert.NoError(t, err) _, err = apc.AddTrack(video2) assert.NoError(t, err) - audio1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus}, "3", "3") + audio1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 48000, Channels: 2}, "3", "3") assert.NoError(t, err) _, err = apc.AddTrack(audio1) assert.NoError(t, err) - audio2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus}, "4", "4") + audio2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 48000, Channels: 2}, "4", "4") assert.NoError(t, err) _, err = apc.AddTrack(audio2) @@ -269,25 +269,25 @@ func TestSDPSemantics_UnifiedPlanWithFallback(t *testing.T) { }) assert.NoError(t, err) - video1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "1", "1") + video1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "1", "1") assert.NoError(t, err) _, err = apc.AddTrack(video1) assert.NoError(t, err) - video2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "2", "2") + video2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"}, "2", "2") assert.NoError(t, err) _, err = apc.AddTrack(video2) assert.NoError(t, err) - audio1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus}, "3", "3") + audio1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 48000, Channels: 2}, "3", "3") assert.NoError(t, err) _, err = apc.AddTrack(audio1) assert.NoError(t, err) - audio2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus}, "4", "4") + audio2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeOpus, ClockRate: 48000, Channels: 2}, "4", "4") assert.NoError(t, err) _, err = apc.AddTrack(audio2) diff --git a/stats_go_test.go b/stats_go_test.go index 45375da7356..8b2321703b6 100644 --- a/stats_go_test.go +++ b/stats_go_test.go @@ -1205,7 +1205,7 @@ func TestPeerConnection_GetStats(t *testing.T) { offerPC, answerPC, err := newPair() assert.NoError(t, err) - track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion1") + track1, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion1") require.NoError(t, err) _, err = offerPC.AddTrack(track1) diff --git a/track_local_static_test.go b/track_local_static_test.go index 5c4f1ddd674..ece2b410b0e 100644 --- a/track_local_static_test.go +++ b/track_local_static_test.go @@ -26,7 +26,7 @@ func Test_TrackLocalStatic_NoCodecIntersection(t *testing.T) { report := test.CheckRoutines(t) defer report() - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) t.Run("Offerer", func(t *testing.T) { @@ -97,7 +97,7 @@ func Test_TrackLocalStatic_Closed(t *testing.T) { _, err = pcAnswer.AddTransceiverFromKind(RTPCodecTypeVideo) assert.NoError(t, err) - vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = pcOffer.AddTrack(vp8Writer) @@ -139,7 +139,7 @@ func Test_TrackLocalStatic_PayloadType(t *testing.T) { answerer, err := NewAPI(WithMediaEngine(mediaEngineTwo)).NewPeerConnection(Configuration{}) assert.NoError(t, err) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = offerer.AddTransceiverFromKind(RTPCodecTypeVideo) @@ -175,7 +175,7 @@ func Test_TrackLocalStatic_Mutate_Input(t *testing.T) { pcOffer, pcAnswer, err := newPair() assert.NoError(t, err) - vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = pcOffer.AddTrack(vp8Writer) @@ -207,7 +207,7 @@ func Test_TrackLocalStatic_Binding_NonBlocking(t *testing.T) { _, err = pcOffer.AddTransceiverFromKind(RTPCodecTypeVideo) assert.NoError(t, err) - vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = pcAnswer.AddTrack(vp8Writer) @@ -235,7 +235,7 @@ func BenchmarkTrackLocalWrite(b *testing.B) { b.Fatalf("Failed to create a PC pair for testing") } - track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(b, err) _, err = offerPC.AddTrack(track) @@ -256,13 +256,13 @@ func BenchmarkTrackLocalWrite(b *testing.B) { func Test_TrackLocalStatic_Padding(t *testing.T) { mediaEngineOne := &MediaEngine{} assert.NoError(t, mediaEngineOne.RegisterCodec(RTPCodecParameters{ - RTPCodecCapability: RTPCodecCapability{MimeType: "video/VP8", ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil}, + RTPCodecCapability: RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil}, PayloadType: 100, }, RTPCodecTypeVideo)) mediaEngineTwo := &MediaEngine{} assert.NoError(t, mediaEngineTwo.RegisterCodec(RTPCodecParameters{ - RTPCodecCapability: RTPCodecCapability{MimeType: "video/VP8", ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil}, + RTPCodecCapability: RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil}, PayloadType: 200, }, RTPCodecTypeVideo)) @@ -272,7 +272,7 @@ func Test_TrackLocalStatic_Padding(t *testing.T) { answerer, err := NewAPI(WithMediaEngine(mediaEngineTwo)).NewPeerConnection(Configuration{}) assert.NoError(t, err) - track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8, ClockRate: 90000}, "video", "pion") assert.NoError(t, err) _, err = offerer.AddTransceiverFromKind(RTPCodecTypeVideo) @@ -285,7 +285,7 @@ func Test_TrackLocalStatic_Padding(t *testing.T) { offerer.OnTrack(func(track *TrackRemote, _ *RTPReceiver) { assert.Equal(t, track.PayloadType(), PayloadType(100)) - assert.Equal(t, track.Codec().RTPCodecCapability.MimeType, "video/VP8") + assert.Equal(t, track.Codec().RTPCodecCapability.MimeType, MimeTypeVP8) for i := 0; i < 20; i++ { // Padding payload