-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(rtp): improve timestamp accuracy #3513
base: master
Are you sure you want to change the base?
fix(rtp): improve timestamp accuracy #3513
Conversation
7230cb5
to
2710caa
Compare
Oops, I changed the title in the commit, but forgot to do the PR. I guess it's still too long anyway:
|
2710caa
to
15f6927
Compare
a6aa913
to
5c2a8e2
Compare
5c2a8e2
to
f8580af
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #3513 +/- ##
=========================================
- Coverage 8.44% 6.18% -2.27%
=========================================
Files 90 66 -24
Lines 16069 11989 -4080
Branches 7633 5584 -2049
=========================================
- Hits 1357 741 -616
+ Misses 14214 11072 -3142
+ Partials 498 176 -322
Flags with carried forward coverage won't be shown. Click here to find out more.
|
I believe that's accurate. The clients that I know of that try to pace audio do it via monitoring the amount of pending audio (either in moonlight-common-c's queue, in the OS audio stack, or both).
AFAIK, Nvidia did their own thing and didn't implement any known RTP FEC standard, so it's asserting what GFE and current Sunshine do. IIUC, what is happening in your case is that you hit the (common) case where a data packet is received first and we synthesize an FEC header using this code:
Since you've adjusted the logic to no longer guarantee that there is
Did you have some idea of how you would "fix it"? AFAICT, it seems basically intrinsic to this model where timestamps are real measured things and not just a glorified counter.
I know Nvidia didn't use it. Given how tiny of a fraction that audio data is of the total traffic, it probably made sense to use the existing Reed-Solomon FEC scheme they were already using for video. They didn't even bother with a variable FEC scheme for audio, unlike video FEC which can change based on client feedback. |
// Audio timestamps are in milliseconds and should be AudioPacketDuration (5ms or 10ms) apart | ||
auto timestamp = static_cast<std::uint32_t>( | ||
std::chrono::duration_cast<std::chrono::microseconds>( | ||
std::chrono::steady_clock::now() - session->audio.timestamp_epoch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's possible to get capture time from the OS too like we do with video frames. IAudioCaptureClient::GetBuffer()
takes an optional pu64QPCPosition
parameter that gives you the timestamp of capture.
* Video: instead of using now() when the RTP packet is created, use the earlier packet->frame_timestamp that we're already collecting for host latency stats. This timestamp should be more accurate to when we captured the frame. I am not sure if all backends support this timestamp, so there is a fallback to the current method. * Audio: fix bug where the RTP timestamps stop advancing when no audio is being sent. Audio now uses the same timer-based source for this field, but remains as milliseconds. * Both use steady_clock and microseconds / 1000 to maintain precision. Video still uses 90khz time base per the spec, and audio is effectively at packet duration resolution of 5ms/10ms.
f8580af
to
da59b33
Compare
Quality Gate passedIssues Measures |
Background
I am experimenting with the iOS AVSampleBufferAudioRenderer and AVSampleBufferRenderSynchronizer APIs, which include the ability to use RTP timestamps as a way to pace playback, provide a/v sync that won't drift, use variable-speed playback to cover for short glitches (such as Game Mode's drop in Bluetooth latency), proper spatial audio support for free, and more. It should also be nicely compatible with the AVSampleBufferDisplayLayer API currently used by the iOS video code. The biggest challenge with these APIs is their higher latency, but I'm hopeful it can get to a reasonable level. Worst case, it could be a good option when you are willing to trade a little latency for solid playback.
Description
Known issue: I had to comment out one assert in Moonlight, because this patch changes one of the FEC timestamps. The FEC RFC says "The timestamp SHALL be set to a time corresponding to the repair packet's transmission time. Note that the timestamp value has no use in the actual FEC protection process and is usually useful for jitter calculations.", so I don't think this assert is correct anyway. Even though this shouldn't affect Moonlight release builds which don't use asserts or the extra FEC verification code, this probably needs to be resolved before this can be accepted, either by only sending correct timestamp packets to newer Moonlight versions, or fixing it in the FEC code. (Not to get too sidetracked but was the Opus FEC support ever tried? I sometimes wonder if the 40% FEC overhead on audio is too high for benefit.)
RtpAudioQueue.c:300
LC_ASSERT_VT(existingBlock->fecHeader.baseTimestamp == fecBlockBaseTs);
Type of Change
.github/...
)Checklist