Skip to content

Do not send Sender Reports before any RTP has been sent - #461

Merged
JoTurk merged 2 commits into
mainfrom
sr-before-first-packet
Sep 15, 2026
Merged

JoTurk merged 2 commits into
mainfrom
sr-before-first-packet

Conversation

@tmatth

@tmatth tmatth commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

The sender report interceptor emitted an SR for every bound stream on each tick, including streams that had not written a single packet. For those the RTP timestamp was derived from a zero time.Time, so the report mapped "now" to a garbage timestamp (2269117121 at 90 kHz, 923864645 at 48 kHz). RFC 3550 6.4 says a source that has sent nothing sends an RR, which the receiver interceptor already does.

Receivers that anchor RTCP-based timing on the first SR they see (for example OvenMediaEngine with RtcpBasedTimestamp) then have their anchor jump when the first real SR arrives a second later, and the stream can be stuck with a PTS that moved backwards by hours.

Skip streams with no packets sent when generating reports. The two existing subtests that relied on an SR before any RTP are adjusted: "before any packet" now asserts nothing is written, and "inject ticker" writes one RTP packet before ticking.

This PR also adds a test specifically for this transition.

@codecov

codecov Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.46%. Comparing base (969e785) to head (71b9984).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #461      +/-   ##
==========================================
+ Coverage   81.29%   81.46%   +0.16%     
==========================================
  Files          91       91              
  Lines        4683     4688       +5     
==========================================
+ Hits         3807     3819      +12     
+ Misses        696      693       -3     
+ Partials      180      176       -4     
Flag Coverage Δ
go 81.46% <100.00%> (+0.16%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tmatth
tmatth force-pushed the sr-before-first-packet branch 3 times, most recently from 3dc8642 to a17959d Compare September 14, 2026 23:33
@tmatth
tmatth requested a review from JoTurk September 14, 2026 23:36

@mengelbart mengelbart left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think this makes sense.

Comment thread pkg/report/sender_interceptor.go Outdated
Comment thread pkg/report/sender_interceptor_test.go Outdated

@JoTurk JoTurk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I agree with @mengelbart comments

@tmatth
tmatth force-pushed the sr-before-first-packet branch from a17959d to 07c51b3 Compare September 15, 2026 12:52
The sender report interceptor emitted an SR for every bound stream on
each tick, including streams that had not written a single packet. For
those the RTP timestamp was derived from a zero time.Time, so the report
mapped "now" to a garbage timestamp (2269117121 at 90 kHz, 923864645 at
48 kHz). RFC 3550 6.4 says a source that has sent nothing sends an RR,
which the receiver interceptor already does.

Receivers that anchor RTCP-based timing on the first SR they see (for
example OvenMediaEngine with RtcpBasedTimestamp) then have their anchor
jump when the first real SR arrives a second later, and the stream can
be stuck with a PTS that moved backwards by hours.

Skip streams with no packets sent when generating reports. The two
existing subtests that relied on an SR before any RTP are adjusted:
"before any packet" now asserts nothing is written, and "inject ticker"
writes one RTP packet before ticking.
Cover the transition directly: a tick before any RTP writes nothing,
and the first tick after one RTP packet writes an SR whose RTPTime is
that packet's timestamp.
@tmatth
tmatth force-pushed the sr-before-first-packet branch from 07c51b3 to 71b9984 Compare September 15, 2026 13:05
@JoTurk
JoTurk merged commit 26f105c into main Sep 15, 2026
19 checks passed
@JoTurk
JoTurk deleted the sr-before-first-packet branch September 15, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants