Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Tentative first pass at making simulcast egest possible #312

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

Draft
robashton wants to merge 38 commits into webrtc-rs:master
base: master
Choose a base branch
Loading
from robashton:simulcast-egest

Conversation

@robashton
Copy link
Member

@robashton robashton commented Oct 7, 2022
edited
Loading

#289 (comment)

Forgot to make a PR and stick my long-winded text there, but whatever, is is the draft PR :)

(I'll fix the tests momentarily, forgot I'd changed a structural thing for the API!)

Copy link
Member

k0nserv commented Oct 7, 2022
edited
Loading

@robashton This looks great! I'm going to look closer next week. I would advise that you review the changes that undo work from #217 however. These fixed bugs and made us more spec compliant and should definitely remain(might need changing though)

Copy link
Member Author

Ah, if I have a source as to "where it came from" then I can do my best to restore it

Copy link
Member Author

ah, yes - now I see where it was being set. By the time I realised that code wasn't working any more I'd lost that line.

Fine, that's easy to restore, will sort that along with the pesky Mutex that shouldn't be a Mutex.

Copy link
Member

k0nserv commented Oct 7, 2022

Great, I think it was only #217 that introduced these changes, but you if you're in doubt it should be clear from git blame. Any part of JSEP that talk about msid and the parts of the spec that discuss RTCRtpSender.[[AssociatedMediaStreamIds]] are relevant to read to make sense of this

Copy link
Member Author

That should be a bit closer to the finish line - I think I got the placement right for the msid / simulcast directives in the SDP

Copy link
Member

@k0nserv k0nserv left a comment

Choose a reason for hiding this comment

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

I think it might be better to leverage an enum for track_encodings, i.e.

enum TrackEncodings {
 Simulcast(Vec<TrackEncoding>),
 Single(TrackEncoding)
}

Copy link
Member Author

I think it might be better to leverage an enum for track_encodings, i.e.

enum TrackEncodings {
 Simulcast(Vec<TrackEncoding>),
 Single(TrackEncoding)
}

I'm not against this, let's get ourselves happy with the rest of the minor bits and I'll have a look at it.

Copy link
Member Author

Just tidying up this thread so I can see what is outstanding, quite keen to get this pushed over the finish line so I can move onto the next task in my queue (not webrtc related).

The SRTP Reader stuff seems the most pressing, I've re-looked at this in the whole and it looks as though it's not 'wrong' per se, we've got independent streams on a shared transport and you want separate binds/interceptors for each of those (or that shared state will get hairy quickly).

The comment about the SRTP Stream being shared I don't think is correct, as we create the SRTP stream per encoding at the top of the function

 let ssrc = rand::random::<u32>();
 let srtp_stream = Arc::new(SrtpWriterFuture {
 closed: AtomicBool::new(false),
 ssrc,
 rtp_sender: Arc::downgrade(&self.internal),
 rtp_transport: Arc::clone(&self.transport),
 rtcp_read_stream: Mutex::new(None),
 rtp_write_session: Mutex::new(None),
 });
 let srtp_rtcp_reader = Arc::clone(&srtp_stream) as Arc<dyn RTCPReader + Send + Sync>;
 let rtcp_reader = self.interceptor.bind_rtcp_reader(srtp_rtcp_reader).await;

Calling close on each of these in sequence is fine (I think). This is spiritually quite close to what Pion is doing with its stack (although I appreciate a lot of that has changd and it may well have fixes in to deal with bugs that might arise with this decisio that I haven't implemented here)

Copy link
Member

k0nserv commented Oct 12, 2022

The comment about the SRTP Stream being shared I don't think is correct, as we create the SRTP stream per encoding at the top of the function

Aight, I misread.

What about RTCP?

let tracks = self.tracks.read().await;
for t in &*tracks {
if t.track.rid()== rid {
if t.track.rid().map_or(false, |r| r == rid) {
Copy link
Member

Choose a reason for hiding this comment

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

I think when comparing to an option option = Some(value) might be easier to read than map_or

Copy link
Member Author

@robashton robashton Oct 13, 2022
edited
Loading

Choose a reason for hiding this comment

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

IIRC, you can't just do a Some(value) because the types don't line up, track.rid() is Option<String> (I toyed with having it be something else, I don't know what the rust convention is and it seemed to match the other types across the codebase) and rid is a &str, so I'd have to make it owned in order to do the comparison which seems even more of a stretch than doing a map_or, which is fundamentally equivalent to the oft-used fromMaybe in a functional language like haskell/purescript.

If the left hand type can be changed then this would go away. If you have a suggestion for this then please do tell (I did start with &Option<String> to avoid the clone but that just pushed the clone to the consumers which was 🤮 )

Copy link
Member

Choose a reason for hiding this comment

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

You can do track.rid().as_deref() == Some(rid) but I guess that's not much better than this. By using as_deref the Deref coercion mechanism kicks in, resulting in a left hand side type of Option<&str>

Copy link
Member Author

@robashton robashton Oct 13, 2022

Choose a reason for hiding this comment

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

That's a neat little feature - would there be benefit in changing the type of track.rid()? It's mostly used in checks just like this anyway

Copy link
Member

Choose a reason for hiding this comment

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

That's a good point actually, it should be Option<&str> to avoid the allocation each time it's called. The caller can still clone it if they want

Copy link
Member Author

@robashton robashton Oct 17, 2022

Choose a reason for hiding this comment

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

Yeah okay, Option<String> on the struct and Option<&str> on the trait is much nicer (and analogous to how you'd do a String anyway), I note that there are plenty of inconsistencies in how strings are passed around in the codebase in general and I've left most of them alone in this change so there are a few unnecessary String::from's here, but on the whole it's much nicer


/// RTPSender allows an application to control how a given Track is encoded and transmitted to a remote peer
pub struct RTCRtpSender {
pub(crate) track_encodings: RwLock<Vec<Arc<TrackEncoding>>>,
Copy link
Member

Choose a reason for hiding this comment

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

I don't expect you need to use an async lock here. As long as the await point isn't being held across awaits a regular sync lock is preferred. See https://tokio.rs/tokio/tutorial/shared-state#on-using-stdsyncmutex

Copy link
Member Author

@robashton robashton Oct 13, 2022

Choose a reason for hiding this comment

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

Hadn't even occured to me which RwLock I'd imported, I'll watch for that in the future

Copy link
Member Author

@robashton robashton Oct 13, 2022

Choose a reason for hiding this comment

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

There is another of these on for the list of tracks on RTCRtpReceiver which I added a few months ago, I guess the same applies for that too

Copy link
Member

Choose a reason for hiding this comment

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

Yeah generally there are a lot of asynchronous locks in this project that should be reconsidered. I suspect a big chunk of these can become sync

rtp_write_session: Mutex::new(None),
});

let srtp_rtcp_reader = Arc::clone(&srtp_stream) as Arc<dyn RTCPReader + Send + Sync>;
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, if you are leaving it like this can we add a TODO about this point?

let mut send_parameters = RTCRtpSendParameters {
rtp_parameters: self
.media_engine
.get_rtp_parameters_by_kind(self.kind, &[RTCRtpTransceiverDirection::Sendonly])
Copy link
Member

Choose a reason for hiding this comment

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

This will conflict with #321 FYI

Copy link
Member Author

Urgh, I didn't mean to push that rebase, I was just looking at what had changed upstream and forgot I'd pulled it when I came back from coffee. What a mess.

Copy link

codecov bot commented Oct 13, 2022
edited
Loading

Codecov Report

❌ Patch coverage is 59.07080% with 185 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.80%. Comparing base (a000977) to head (7c03a11).
⚠️ Report is 616 commits behind head on master.

Files with missing lines Patch % Lines
...hannels-flow-control/data-channels-flow-control.rs 0.00% 118 Missing ⚠️
...tion/allocation_manager/allocation_manager_test.rs 61.36% 0 Missing and 17 partials ⚠️
...src/track/track_local/track_local_static_sample.rs 25.00% 8 Missing and 4 partials ⚠️
...tc/src/peer_connection/peer_connection_internal.rs 47.05% 6 Missing and 3 partials ⚠️
...tc/src/track/track_local/track_local_static_rtp.rs 55.00% 4 Missing and 5 partials ⚠️
ice/src/agent/agent_gather_test.rs 44.44% 0 Missing and 5 partials ⚠️
examples/examples/simulcast/simulcast.rs 0.00% 4 Missing ⚠️
webrtc/src/api/media_engine/media_engine_test.rs 77.77% 1 Missing and 3 partials ⚠️
ice/src/agent/agent_gather.rs 86.66% 0 Missing and 2 partials ⚠️
.../src/rtp_transceiver/rtp_sender/rtp_sender_test.rs 0.00% 0 Missing and 2 partials ⚠️
... and 3 more
Additional details and impacted files
@@ Coverage Diff @@
## master #312 +/- ##
==========================================
+ Coverage 56.62% 56.80% +0.17% 
==========================================
 Files 500 500 
 Lines 47517 47714 +197 
 Branches 12850 12861 +11 
==========================================
+ Hits 26907 27103 +196 
+ Misses 9943 9920 -23 
- Partials 10667 10691 +24 

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Member Author

The comment about the SRTP Stream being shared I don't think is correct, as we create the SRTP stream per encoding at the top of the function

Aight, I misread.

What about RTCP?

I've re-read the code around this, and as far as I can see, the infrastructure-per-encoding model works because each encoding has its own SSRC and that is how the SrtpWriterFuture discriminates when it sets itself up. (The SrtpWriterfuture being where the RTCP reader comes from) and that being how read_simulcast then works.

It's a bit of a janky model, but it's the one we've got - I don't know how you'd avoid setting this up per-encoding without changing a heap of other code?

Copy link
Member

@k0nserv k0nserv left a comment

Choose a reason for hiding this comment

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

Could you try and clean up the git strangeness and I can do a final pass

## Unreleased
* Add IP filter to ICE `AgentConfig` [#306](https://github.com/webrtc-rs/webrtc/pull/306)

* Add IP filter to ICE `AgentConfig` [#306](https://github.com/webrtc-rs/webrtc/pull/306) and [#318](https://github.com/webrtc-rs/webrtc/pull/318).
Copy link
Member

Choose a reason for hiding this comment

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

Something is off here this change shouldn't be in this branch


if !ipaddr.is_loopback()
&& ((ipv4requested && ipaddr.is_ipv4()) || (ipv6requested && ipaddr.is_ipv6()))
&& ip_filter
Copy link
Member

Choose a reason for hiding this comment

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

Why is this diff here, this is already the code on master, something must've gone wrong with rebasing

Copy link
Member Author

Could you try and clean up the git strangeness and I can do a final pass

If I can work out how, I totally messed this one up, usually I'd just do a git fetch and a rebase on final pass (and from the other side). That I did a pull to check what had changed upstream and then accidentally pushed it is a total cluster.

I imagine my best bet might be to do an interactive rebase locally and re-apply my changes without any of that noise in it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@k0nserv k0nserv k0nserv left review comments

+1 more reviewer

@lolgesten lolgesten lolgesten left review comments

Reviewers whose approvals may not affect merge requirements

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /