Problem:
--------
Firefox (testing with Firefox 93) sends an `offer`
with simulcast track which includes both RIDs and SSRCs.
When track details are gathered, RIDs are fetched
using `getRids` which returns a map. A `range` is
done on the returned map and RIDs are appended to
the `rids` array in `trackDetails`.
And then SSRCs are read from SDP and set into the
`ssrcs` array of `trackDetails`.
As map range order is not guaranteed, some times
the RID index and SSRC index in their respective arrays
do not match.
Due to the mismatch, services like ion-sfu which rely
on RID to find the correct spatial layer get confused
and end up forwarding the wrong layer.
Solution(s):
------------
There are three possible solutions I could think of
1. The simplest is to not populate SSRCs in `trackDetails`
if RIDs are available. Let `handleIncomingSSRC` do the
SSRC resolution based on RID.
According to RFC 8853 (https://www.ietf.org/rfc/rfc8853.pdf),
the binding to SSRC should happen using RID.
This is the change I have made in this PR. See testing
below for browsers tested.
2. Look for `simulcast` attribute in SDP and take
the RID ordering from that line in `getRids` if that
attribute is available. If not fall back to `rid` attribute.
Also, change `getRids` to return an array.
But, I cannot find an RFC which defines behaviour when
both RID and SSRC are used in `offer`. The question is,
"Will the `ssrc` attribute ordering match the `rid`
ordering?". If that is not guaranteed, this will run
into trouble.
This should be easy to do though if we want to go down this
route.
3. The hardest option is to change the receiver SSRC based
on RID. But, that makes it too complicated (for example
if we have to change SSRC binding of a receiver based on
received RID, there will be two receivers with the same SSRC
binding unless there is some way to swap bindings of receivers)
Testing:
--------
Tested on Firefox, Firefox 78.15.0esr, Chrome, Ssafari and
ensured that Simulcast sender and receiver are in sync for
rid/ssrc/spatial layer resolution.
Using an improvment of pion/datachannel, the channel opener can now
set an event to be called when the DATA_CHANNEL_ACK message is recieved
Resolves#1063
Relates to pion/datachannel#81
github.com/pion/rtp to v1.7.4 fixed the parsing of padding bytes as
media payload. This fix skips over RTP packets with an empty payload,
such as unmarshalled padding only packets.
When filtering SSRCes we were running the filter operation on the source
slice and not the filtered slice. Causing us to ignore all the filter
operations that had been previously run.
Problem:
--------
In the following negotiation sequence, the Simulcast track is lost.
1. Remote Offer with Simulcast tracks with rids
2. A new track added to Remote Offer with tracks using SSRCs
When the updated `offer` is received, the Simulcast transceiver's
receiver gets overwritten because the tracks from SDP is compared
against current transceivers. The current transceiver for the
Simulcast track already had SSRCs set as media has been received.
But, tracks read from the SDP only has `rid`. So, no current
transceiver matches and hence a new receiver is created which
clobeers the good Simulcast receiver.
Fix:
----
- Prioritize search by `rid`.
- Also found a case of a loop where the index was missing entries
in the loop. Fix it.
Testing:
--------
- The above case works
Issue:
------
A transceiver's codecs can be modified using `SetCodecPreferences`.
When retrieving codecs from the transceiver after changing codec
preferences of the transceiver (for example changing the SDPFmtpLine),
the filter function was using codec from the media engine. Thus,
the change from `SetCodecPreferences` is lost.
Fix:
----
- When a match is found (either exact or partial), use the codec from
the transceiver instead of media engine.
- Based on feedback, add checks to ensure that PayloadType is not
set incorrectly (i. e. set with a default of 0). If it is set to 0,
use the PayloadType from the media engine, i. e. negotiated value.
Testing:
--------
- Modify SDPFmtpLine of a codec of a transceiver using
`SetCodecPreferences` method of `RTPTransceiver`.
- Invoke `GetParamters` of `RTPREceiver` and ensure that `Codecs`
has the SDPFmtpLine modification. Before this change the change
was not reflected in the returned `Codecs`.
- Check that SDP has payload from codec set via SetCodecPreferences
This reverts commit 6c3620093d.
This commit would cause sender.ReadRTCP() to never return
even when pc associated with this sender was closed.
The aftermath is leaked goroutines that will never stop.
Interceptors are being accidentally misused by users.
The issue is that an Interceptor can be re-used between
multiple PeerConnections. Interceptors were designed to only be
single PeerConnection aware, so state is being corrupted.
Instead we are now going to provide InterceptorFactories. The default
API of pion/webrtc will now be safe to use between PeerConnections.
Resolves webrtc#1956
Read + Discard packets from the Simulcast repair stream. When a
Simulcast stream is enabled the remote will send packets via the repair
stream for probing. We can't ignore these packets anymore because it
will cause gaps in the feedback reports
Resolves#1957
Add functions to configure TWCC reports and TWCC header extensions.
Only TWCC reports are enabled by default, because there is no Congestion
Controller available to handle reports from a remote peer, yet.
(*SCTPTransport).generateAndSetDataChannelID performed a double loop to
find the next available data channel ID. This changes that behavior to
generate a lookup map with the taken IDs first, so generating a data
channel ID takes much less time.
Before, it would take more than 1000ms to generate the next data channel
ID once you had roughly 50k of them. Now it only takes 4ms at that same
point.
Fixes#1945
In RtpSender, if Read has been called and wait for srtpReady,
then if we call Close() immediately after
rtpSender.trasport.srtpReady, that means srtpWriterFuture's Close
may be called when it's init method is executing.
In Read -> init, goroutine may run at:
rtpWriteStream, err := srtpSession.OpenWriteStream()
if err != nil {
return err
}
s.rtcpReadStream.Store(rtcpReadStream)
s.rtpWriteStream.Store(rtpWriteStream)
In Close, goroutine may run at
if value := s.rtcpReadStream.Load(); value != nil {
return value.(*srtp.ReadStreamSRTCP).Close()
}
return nil
s.rtcpReadStream could be nil in the check at Close, so it
will not be closed.
And in Read method, the init method initiates the stream and
return. Then read at the stream's buffer, and blocked infinite
because the buffer is not closed. And it will not be closed
if you call RtpSender's close method because it is already
closed.
Add an accessor to make getting value easy. Also add
TestPeerConnection_SkipStoppedTransceiver. This commit also cleans
up RTPTransceiver creation. We used a helper function, when we should
have just used the provide constructor
Before we wouldn't start the undeclaredMediaProcessor until SCTP had
finished. If SCTP never finishes an inbound RTP packet with an unknown
SSRC would cause all RTP processing to hang.
When attempting to interact with a WebRTC service a user was getting a
DTLS alert of UnknownCA. The remote service was asserting the lifetime +
subject of the certificate. This PR modifies Pion's certificate
generation code to match libwebrtc so it can work with the WebRTC
service.
Resolves#1940
If we have a media section with no SSRC we would fire an OnTrack. This
code now properly ignores a MediaSection that has a rid attribute.
Resolves#1808
Both partition head and tail checking is now done in the
depacketizer. For backwards compatibility, there are stubs
for PartitionHeadChecker and WithPartitionHeadChecker that do
nothing; these should be removed for 4.0.
This also fixes a bug with the depacketizer: if no head checker
was present, every packet would be considered as a potential
partition head, even if it was at the beginning of the buffer.
Since a partition head checker is now always present, the bug
cannot happen.
The tests assume the old bug, which is why the fakePacketizer
returns true if headBytes is empty. It would be better to adapt
the tests to do the right thing, as in jech/depacketizer.
This gives an option to raise the receive MTU as SettingEngine option.
If SettingEngine has not been set the MTU, then default value is used
instead, 1460
Resolves#1925
It isn't possible to send media if a MediaEngine has no codecs. This
catches a common misconfiguration issues that users find themselves in.
Resolves#1702