Skip to content

Commit

Permalink
Disable MediaEngine Copy by Default
Browse files Browse the repository at this point in the history
If an API is shared between PeerConnections they would use the same
MediaEngine. A MediaEngine contains negotiated PayloadTypes so if the
PeerConnections were answering you would end up in invalid states.

Add DisableMediaEngineCopy to SettingEngine in case user needs old
behavior.

Resolves #1662
  • Loading branch information
Sean-Der committed Feb 10, 2021
1 parent b5fa979 commit c4944cc
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 0 deletions.
10 changes: 10 additions & 0 deletions mediaengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,16 @@ func (m *MediaEngine) getHeaderExtensionID(extension RTPHeaderExtensionCapabilit
return
}

// copy copies any user modifiable state of the MediaEngine
// all internal state is reset
func (m *MediaEngine) copy() *MediaEngine {
return &MediaEngine{
videoCodecs: append([]RTPCodecParameters{}, m.videoCodecs...),
audioCodecs: append([]RTPCodecParameters{}, m.audioCodecs...),
headerExtensions: append([]mediaEngineHeaderExtension{}, m.headerExtensions...),
}
}

func (m *MediaEngine) getCodecByPayload(payloadType PayloadType) (RTPCodecParameters, RTPCodecType, error) {
for _, codec := range m.negotiatedVideoCodecs {
if codec.PayloadType == payloadType {
Expand Down
4 changes: 4 additions & 0 deletions peerconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ func NewPeerConnection(configuration Configuration) (*PeerConnection, error) {

// NewPeerConnection creates a new PeerConnection with the provided configuration against the received API object
func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, error) {
if !api.settingEngine.disableMediaEngineCopy {
api.mediaEngine = api.mediaEngine.copy()
}

// https://w3c.github.io/webrtc-pc/#constructor (Step #2)
// Some variables defined explicitly despite their implicit zero values to
// allow better readability to understand what is happening.
Expand Down
8 changes: 8 additions & 0 deletions settingengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type SettingEngine struct {
LoggerFactory logging.LoggerFactory
iceTCPMux ice.TCPMux
iceProxyDialer proxy.Dialer
disableMediaEngineCopy bool
}

// DetachDataChannels enables detaching data channels. When enabled
Expand Down Expand Up @@ -255,3 +256,10 @@ func (e *SettingEngine) SetICETCPMux(tcpMux ice.TCPMux) {
func (e *SettingEngine) SetICEProxyDialer(d proxy.Dialer) {
e.iceProxyDialer = d
}

// DisableMediaEngineCopy stops the MediaEngine from being copied. This allows a user to modify
// the MediaEngine after the PeerConnection has been constructed. This is useful if you wish to
// modify codecs after signaling. Make sure not to share MediaEngines between PeerConnections.
func (e *SettingEngine) DisableMediaEngineCopy(isDisabled bool) {
e.disableMediaEngineCopy = isDisabled
}
43 changes: 43 additions & 0 deletions settingengine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,46 @@ func TestSettingEngine_SetICETCP(t *testing.T) {

assert.Equal(t, tcpMux, settingEngine.iceTCPMux)
}

func TestSettingEngine_SetDisableMediaEngineCopy(t *testing.T) {
t.Run("Copy", func(t *testing.T) {
m := &MediaEngine{}
assert.NoError(t, m.RegisterDefaultCodecs())

offerer, answerer, err := NewAPI(WithMediaEngine(m)).newPair(Configuration{})
assert.NoError(t, err)

_, err = offerer.AddTransceiverFromKind(RTPCodecTypeVideo)
assert.NoError(t, err)

assert.NoError(t, signalPair(offerer, answerer))

assert.False(t, m.negotiatedVideo)
assert.Empty(t, m.negotiatedVideoCodecs)

assert.NoError(t, offerer.Close())
assert.NoError(t, answerer.Close())
})

t.Run("No Copy", func(t *testing.T) {
m := &MediaEngine{}
assert.NoError(t, m.RegisterDefaultCodecs())

s := SettingEngine{}
s.DisableMediaEngineCopy(true)

offerer, answerer, err := NewAPI(WithMediaEngine(m), WithSettingEngine(s)).newPair(Configuration{})
assert.NoError(t, err)

_, err = offerer.AddTransceiverFromKind(RTPCodecTypeVideo)
assert.NoError(t, err)

assert.NoError(t, signalPair(offerer, answerer))

assert.True(t, m.negotiatedVideo)
assert.NotEmpty(t, m.negotiatedVideoCodecs)

assert.NoError(t, offerer.Close())
assert.NoError(t, answerer.Close())
})
}

0 comments on commit c4944cc

Please sign in to comment.