From ff08b857003c98b7645319903147782d271d97c2 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Sat, 28 Jun 2025 16:56:44 +0200 Subject: [PATCH] server: add ServerStreamStatsFormat.LocalSSRC (#804) --- client_record_test.go | 2 +- server_play_test.go | 17 ++++++++++++++++- server_session.go | 11 ++++++++--- server_stream.go | 27 ++++++--------------------- server_stream_format.go | 9 +++++++++ server_stream_stats.go | 2 ++ 6 files changed, 42 insertions(+), 26 deletions(-) diff --git a/client_record_test.go b/client_record_test.go index 24e9023d..99566d31 100644 --- a/client_record_test.go +++ b/client_record_test.go @@ -46,7 +46,7 @@ var testRTPPacket = rtp.Packet{ CSRC: []uint32{}, SSRC: 0x38F27A2F, }, - Payload: []byte{1, 2, 3, 4}, + Payload: []byte{5, 2, 3, 4}, } var testRTPPacketMarshaled = mustMarshalPacketRTP(&testRTPPacket) diff --git a/server_play_test.go b/server_play_test.go index a744ce97..cde7e573 100644 --- a/server_play_test.go +++ b/server_play_test.go @@ -2427,7 +2427,22 @@ func TestServerPlayStreamStats(t *testing.T) { require.NoError(t, err) st := stream.Stats() - require.Equal(t, uint64(16*2), st.BytesSent) + require.Equal(t, &ServerStreamStats{ + BytesSent: 32, + RTPPacketsSent: 2, + Medias: map[*description.Media]ServerStreamStatsMedia{ + stream.Description().Medias[0]: { + BytesSent: 32, + RTCPPacketsSent: 0, + Formats: map[format.Format]ServerStreamStatsFormat{ + stream.Description().Medias[0].Formats[0]: { + RTPPacketsSent: 2, + LocalSSRC: 955415087, + }, + }, + }, + }, + }, st) } func TestServerPlayBackChannel(t *testing.T) { diff --git a/server_session.go b/server_session.go index df0ab599..877664e1 100644 --- a/server_session.go +++ b/server_session.go @@ -1085,9 +1085,14 @@ func (ss *ServerSession) handleRequestInner(sc *ServerConn, req *base.Request) ( panic("stream cannot be different than the one returned in previous OnSetup call") } - ssrc, ok := stream.localSSRC(medi) - if ok { - th.SSRC = &ssrc + // Fill SSRC if there is a single SSRC only + // since the Transport header does not support multiple SSRCs. + if len(stream.medias[medi].formats) == 1 { + format := stream.medias[medi].formats[medi.Formats[0].PayloadType()] + ssrc, ok := format.localSSRC() + if ok { + th.SSRC = &ssrc + } } } diff --git a/server_stream.go b/server_stream.go index 574d112d..a5b58786 100644 --- a/server_stream.go +++ b/server_stream.go @@ -152,6 +152,12 @@ func (st *ServerStream) Stats() *ServerStreamStats { for _, fo := range sm.formats { ret[fo.format] = ServerStreamStatsFormat{ RTPPacketsSent: atomic.LoadUint64(fo.rtpPacketsSent), + LocalSSRC: func() uint32 { + if v, ok := fo.localSSRC(); ok { + return v + } + return 0 + }(), } } @@ -165,27 +171,6 @@ func (st *ServerStream) Stats() *ServerStreamStats { } } -func (st *ServerStream) localSSRC(medi *description.Media) (uint32, bool) { - st.mutex.Lock() - defer st.mutex.Unlock() - - sm := st.medias[medi] - - // localSSRC() is used to fill SSRC inside the Transport header. - // if there are multiple formats inside a single media stream, - // do not return anything, since Transport headers don't support multiple SSRCs. - if len(sm.formats) > 1 { - return 0, false - } - - stats := firstFormat(sm.formats).rtcpSender.Stats() - if stats == nil { - return 0, false - } - - return stats.LocalSSRC, true -} - func (st *ServerStream) rtpInfoEntry(medi *description.Media, now time.Time) *headers.RTPInfoEntry { st.mutex.Lock() defer st.mutex.Unlock() diff --git a/server_stream_format.go b/server_stream_format.go index 0498ae50..8e7bb653 100644 --- a/server_stream_format.go +++ b/server_stream_format.go @@ -35,6 +35,15 @@ func (sf *serverStreamFormat) initialize() { sf.rtcpSender.Initialize() } +func (sf *serverStreamFormat) localSSRC() (uint32, bool) { + stats := sf.rtcpSender.Stats() + if stats != nil { + return stats.LocalSSRC, true + } + + return 0, false +} + func (sf *serverStreamFormat) writePacketRTP(byts []byte, pkt *rtp.Packet, ntp time.Time) error { sf.rtcpSender.ProcessPacket(pkt, ntp, sf.format.PTSEqualsDTS(pkt)) diff --git a/server_stream_stats.go b/server_stream_stats.go index 6e845a6e..e83a1ecf 100644 --- a/server_stream_stats.go +++ b/server_stream_stats.go @@ -9,6 +9,8 @@ import ( type ServerStreamStatsFormat struct { // number of sent RTP packets RTPPacketsSent uint64 + // local SSRC + LocalSSRC uint32 } // ServerStreamStatsMedia are stream media statistics.