-
Notifications
You must be signed in to change notification settings - Fork 81
Add interceptor to aggregate CCFB reports #300
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
base: master
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #300 +/- ##
==========================================
+ Coverage 78.64% 78.95% +0.31%
==========================================
Files 82 86 +4
Lines 5165 5493 +328
==========================================
+ Hits 4062 4337 +275
- Misses 929 974 +45
- Partials 174 182 +8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This is so exciting! I am glad to see you back @mengelbart :) @jech and @JoeTurki are getting deep into this world if you are looking for people to work with/quick reviews |
271a101
to
1fb32cc
Compare
Could you please give some background? Why not simply provide a function that parses the reports? To my untrained eyes, it looks like your interceptor aims to allow a client to do: _, attr, _ := track.ReadRTCP()
data := attr.Get(CCFBAttributesKey) Without an interceptor, the same code would look like this: p, _, _ := track.ReadRTCP()
var data CCFBReportPacket
data.Unmarshal(p.Data) Now, perhaps I'm biased against interceptors (which are causing me a fair amount of suffering), but the second code looks clearer to me. What am I missing? |
The interceptor also keeps track of outgoing RTP packets, timestamps them, and matches RTCP reports to the history of sent packets. The report you get from the attributes then contains departure and arrival timestamps for each packet that was reported on in the RTCP. Without the interceptor, you have to keep track of the departure timestamps yourself. |
5244e8b
to
7ad4eec
Compare
89e56ac
to
b8e4acd
Compare
1072695
to
abbd5eb
Compare
561a285
to
842f423
Compare
I tried to make all of the new linters happy, but I added |
dc4d48f
to
27d47e8
Compare
Hi @mengelbart what a cool PR! I'm curious to learn what's the relationship between this interceptor, the pacer, and bandwidth estimator GCC will be like by your design. For users using this interceptor, they need to make sure it goes after the pacer right? Otherwise the captured send time will be incorrect. I also take a brief look at the GCC refactor, and it seems like pacing is not included in it. |
pkg/ccfb/interceptor.go
Outdated
} | ||
} | ||
|
||
func twccConverterFactory(f func(feedback *rtcp.TransportLayerCC) (time.Time, map[uint32][]acknowledgement)) Option { |
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.
Looks like twcc is supported too (not just rfc8888), should we update the description and title of this PR?
@3DRX right, pacing is not included in the GCC refactoring PR, because the new design only works on received feedback and everything it does is independent of the packet transmission part. Pacing can still be done in a new interceptor or even before writing packets to the track. |
27d47e8
to
66841af
Compare
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.
looks good to me, thank you
pkg/ccfb/interceptor.go
Outdated
} | ||
ssrcToPrl := map[uint32][]PacketReport{} | ||
for ssrc, reportList := range reportLists { | ||
prl := i.ssrcToHistory[ssrc].getReportForAck(reportList) |
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.
Correct me if I'm wrong, but could this panic if there's no history?
It also seems like it could be abused to trigger a panic for an SSRC that doesn’t have any history yet (though I’m not sure if that’s actually possible).
Additionally, is there a potential race condition here with BindLocalStream?
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.
Good points. I added a check and skip for unknown SSRCs. I also made the lock an RWLock so we can concurrently read the history map for sending RTP packets and receive RTCP packets. And I added a lock around the missing header extension error case in the RTPWriter.
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.
Thanks!
4c65746
to
eacb42d
Compare
eacb42d
to
bd848cd
Compare
fa6203c
to
2217813
Compare
Description
This interceptor keeps track of outgoing RTP packets and reads incoming CCFB (RFC8888) RTCP packets. For each incoming CCFB packet, it creates a report of the included acknowledgments and stores it in the interceptor attributes. Applications reading RTCP packets from it can read the report, e.g., to perform bandwidth estimation.
This is a PoC to improve bandwidth estimation in Pion. The current GCC implementation is hard to use and test. Giving applications access to the feedback reports could simplify and decouple the actual bandwidth estimation from the interceptors.
TODO