Ok, I think I've got a bit of info here:
RTCP with an ssrc of 1 gets dropped
in RtpChannelDatagramFilter::acceptRTCP. That method checks if the
sender ssrc is in the RTPChannel's ssrcs and, if not, drops it. The
RTPChannel's ssrcs get populated
via RTPChannel::acceptDataInputStreamDatagramPacket. When
acceptDataInputStreamDatagramPacket sees a packet with a new ssrc, it
adds it via addReceiveSSRC. RTCP is processed
in acceptControlInputStreamDatagramPacket and only RTCP bye messages are
examined (and handled via calling removeReceiveSSRC), logic for adding a
receive ssrc doesn't exist inside of
acceptControlInputStreamDatagramPacket, so it's not possible for an ssrc
of 1 (sent only via RTCP) to get added there.
The problem here stems from the way RTCP packets are demultiplexed between channels. With bundle both audio and video use the same socket, and RtpChannelDatagramFilter is used for each packet on the socket, and it's purpose is to determine whether the given packet belongs to its RtpChannel.
For RTP packets this is done on the basis of the Payload Type (which is why Payload Types for each channel must be signaled to the bridge). For RTCP packets, however, this is done on the basis of the Packet Sender SSRC.
Now, RtpChannel.accept*InputStreamDatagramPacket is only called for packets which have passed the RtpChannelDatagramFilter test, so if it executes for an RTCP packet, then the SSRC is already in receiveSSRCs.
The reason we update receiveSSRCs on reception of RTP packets, is to allow the recognition of RTCP packets for these streams in the absence of signaled SSRCs. However, for receive-only endpoints, this doesn't work, and their SSRCs (or "1" in your case) need to be signaled through COLIBRI.
As for 'ssrcs' and 'sources' in colibri, this is what I see:
1) The 'ssrcs' field is ignored when issuing a colibri patch to the
bridge, but when a get is requested, it is populated with the values
added via addReceiveSSRC.
I think this might be something used by the Jitsi client, in order to match the remove peers to SSRCs without signalling them in Jingle. AFAIK this isn't used anywhere in a Jitsi-Meet scenario, and I think you can just ignore it.
2) The 'sources' field will populate the 'ssrcs' value when issuing a
colibri patch (it will take those values and call addReceiveSSRC),
however when doing a get, the 'sources' field is populated with the
BRIDGE source ssrcs (the dummy audio and video streams). This comes
from RtpChannel::describe where it fills in the 'sources' field with its
If I add the "1" ssrc as a source, it properly gets added as a receive
ssrc, which means that when RtpChannelDatagramFilter::acceptRTCP sees an
RTCP packet with a sender ssrc of "1", it will forward it correctly.
This is the intention, and this is the way we signal SSRCs in Jitsi-Meet/Jicofo.
So it seems that there are some conflicting definitions/usages of
'ssrcs' and 'sources' in a channel. It appears as though "sources" are
meant to reflect streams coming from the bridge (but they only ever seem
to contain the streams which *originate* at the bridge, not the ones it
forwards), and "ssrcs" are the streams that the bridge should expect to
receive on that channel (either via the rtp packet ssrc or the
senderssrc field in an rtcp packet).
I think the idea is that "sources" sent *to* the bridge contain the SSRCs which it should expect on the given channel, while "sources" sent *from* the bridge contain the SSRCs of streams that belong to the bridge.
So a couple options that came to mind were:
1) Signal the "1" ssrc via the 'sources' block in colibri. This works,
but seems to further contribute to the current confusion in how
'sources' and 'ssrcs' are used. Also, other ssrcs don't need to be
explicitly signaled (they get added automatically) so this doesn't seem
to be very consistent with existing behavior. This wouldn't break
existing clients, but failing to make this change will break clients
based on chrome when their in recvonly for video.
IIRC, we left this to the client/conference focus to take care of (i.e. make sure that SSRCs are signaled even for receive-only endpoints). I think this is reasonable, since WebRTC endpoints require the SSRCs anyway (except for that corner case where they know what to do with "1").
2) Have the acceptDataInputStreamDatagramPacket add any new sender ssrcs
it sees automatically, this matches what we do with normal rtp ssrcs and
would not require any changes from clients.
3) Always require ssrcs to be signaled explicitly. Never add a ssrc
implicitly, only accept those that have been signaled explicitly and
require the client to configure the ssrcs correctly. This would break
We do what we can to work without explicitly signaled SSRCs, but I don't see anything practical that we can do in the case of receive-only endpoints.
At some point we discussed decrypting the RTCP packet, somehow finding its "destination" SSRC (which would depend on the type of RTCP packet), searching for another channel (either audio or video) which has the destination SSRC. But that's very involved.
Regardless of which option (the above or something else) we choose to
solve this, I think there is some cleanup to be done around the usage of
'sources' and 'ssrcs' as well.
I would suggest properly documenting both of them, and possibly adding an option to disable the use of "ssrcs".
On 05/11/15 17:58, Brian Baldino wrote:
On 06/11/15 16:31, Brian Baldino wrote:
> Slight correction, the fix described in #2 would actually be done in
> RtpChannelDatagramFilter::acceptRTCP (since this is where the RTCP is
> dropped now, and is called before
> RTPChannel::acceptControlInputStreamDatagramPacket). We have access to
> the channel there, so we would be able to call addReceiveSSRC.
The problem here is that for each RTCP packet we call RtpChannelDatagramFilter#acceptRTCP twice -- once on the audio channel, and once on the video channel.