From 76634b143ae22da23f827df96b9a482176e8b10d Mon Sep 17 00:00:00 2001 From: Eric Daniels Date: Tue, 15 Oct 2024 12:04:40 -0400 Subject: [PATCH] Add SetFireOnTrackBeforeFirstRTP --- peerconnection.go | 4 ++++ settingengine.go | 10 ++++++++ settingengine_test.go | 54 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/peerconnection.go b/peerconnection.go index 35823660d2c..4b2a16e39ca 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -1245,6 +1245,10 @@ func (pc *PeerConnection) startReceiver(incoming trackDetails, receiver *RTPRece return } + if pc.api.settingEngine.fireOnTrackBeforeFirstRTP { + pc.onTrack(t, receiver) + return + } go func(track *TrackRemote) { b := make([]byte, pc.api.settingEngine.getReceiveMTU()) n, _, err := track.peek(b) diff --git a/settingengine.go b/settingengine.go index f3c70707c9a..2e37b4e74e0 100644 --- a/settingengine.go +++ b/settingengine.go @@ -101,6 +101,7 @@ type SettingEngine struct { srtpProtectionProfiles []dtls.SRTPProtectionProfile receiveMTU uint iceMaxBindingRequests *uint16 + fireOnTrackBeforeFirstRTP bool } // getReceiveMTU returns the configured MTU. If SettingEngine's MTU is configured to 0 it returns the default @@ -491,3 +492,12 @@ func (e *SettingEngine) SetSCTPRTOMax(rtoMax time.Duration) { func (e *SettingEngine) SetICEBindingRequestHandler(bindingRequestHandler func(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool) { e.iceBindingRequestHandler = bindingRequestHandler } + +// SetFireOnTrackBeforeFirstRTP sets if firing the OnTrack event should happen +// before any RTP packets are received. Setting this to true will +// have the Track's Codec and PayloadTypes be initially set to their +// zero values in the OnTrack handler. +// Note: This does not yet affect simulcast tracks. +func (e *SettingEngine) SetFireOnTrackBeforeFirstRTP(fireOnTrackBeforeFirstRTP bool) { + e.fireOnTrackBeforeFirstRTP = fireOnTrackBeforeFirstRTP +} diff --git a/settingengine_test.go b/settingengine_test.go index 4a5714e1f69..6912694f497 100644 --- a/settingengine_test.go +++ b/settingengine_test.go @@ -340,3 +340,57 @@ func TestSetHooks(t *testing.T) { t.Errorf("Failed to set DTLS Certificate Request Hook") } } + +func TestSetFireOnTrackBeforeFirstRTP(t *testing.T) { + lim := test.TimeOut(time.Second * 30) + defer lim.Stop() + + report := test.CheckRoutines(t) + defer report() + + s := SettingEngine{} + s.SetFireOnTrackBeforeFirstRTP(true) + + mediaEngineOne := &MediaEngine{} + assert.NoError(t, mediaEngineOne.RegisterCodec(RTPCodecParameters{ + RTPCodecCapability: RTPCodecCapability{MimeType: "video/VP8", 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}, + PayloadType: 200, + }, RTPCodecTypeVideo)) + + offerer, err := NewAPI(WithMediaEngine(mediaEngineOne), WithSettingEngine(s)).NewPeerConnection(Configuration{}) + assert.NoError(t, err) + + answerer, err := NewAPI(WithMediaEngine(mediaEngineTwo)).NewPeerConnection(Configuration{}) + assert.NoError(t, err) + + track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion") + assert.NoError(t, err) + + _, err = offerer.AddTransceiverFromKind(RTPCodecTypeVideo) + assert.NoError(t, err) + + _, err = answerer.AddTrack(track) + assert.NoError(t, err) + + onTrackFired, onTrackFiredFunc := context.WithCancel(context.Background()) + offerer.OnTrack(func(track *TrackRemote, _ *RTPReceiver) { + _, _, err = track.Read(make([]byte, 1500)) + assert.NoError(t, err) + assert.Equal(t, track.PayloadType(), PayloadType(100)) + assert.Equal(t, track.Codec().RTPCodecCapability.MimeType, "video/VP8") + + onTrackFiredFunc() + }) + + assert.NoError(t, signalPair(offerer, answerer)) + + sendVideoUntilDone(onTrackFired.Done(), t, []*TrackLocalStaticSample{track}) + + closePairNow(t, offerer, answerer) +}