Commit Graph

58 Commits

Author SHA1 Message Date
cnderrauber 7a7fc09372 Add fps calculator for VP8 and DependencyDescriptor (#1110)
* Add fps calculator for VP8 and DependencyDescriptor

* clean code

* unit test

* clean code

* solve comment
2022-10-26 09:28:28 +08:00
Raja Subramanian 222ce5d1a8 Notify max layer taking into account overshoot. (#1117)
* Notify max layer taking into account overshoot.

An attempt to handle case of FF stopping layer 0, but not layer 1.
When max subscribed layer is layer 0, server allows overshoot to layer 1
to ensure continued streaming when the channel is not congested.

But, dynacast could have reported maximum subscribed layer as layer 0.

This is a very simple attempt to address that by taking overshoot
into account. Needs testing if this works well or not.

NOTE: When subsriber/down track is unmuted, it will report
the max subscribed layer as the max required layer. In those cases,
if the client does not start layer 0, there will still be an issue.
IOW, server is not keeping track of client behaviour that the client
has stopped layer 0 and publishing only layer 1. Server is just
accommodating overshoot with this change.

* Fix a couple of tests and change reflect.DeepEqual -> require.Equal as
much as possible
2022-10-23 22:46:01 +05:30
Raja Subramanian b9894ab014 Allocate packetMeta up front to reduce number of allocations. (#1108) 2022-10-20 14:31:19 +05:30
Raja Subramanian 573850261a Cache RTPStats and seed on re-use (#1080)
* Cache RTPStats and seed on re-use

When a cached down track is re-used, RTPStats was not cached.
This caused sender reports getting out-of-sync with the remote side.
Cache RTPStats and seed it on re-use.

* staticcheck
2022-10-12 09:10:17 +05:30
David Zhao 1019faa0e6 Cleanup pass through logging (#1073)
* added filtering for noisy pion logs
* demoted some logs to debug
* using consistent trackID / participant / publisher / subscriber terminology
* removed ice candidate log lines, deferring to combined log
2022-10-06 23:48:37 -07:00
Raja Subramanian d70843bc5a Some logging tweaks (#1048) 2022-09-28 23:54:40 +05:30
Raja Subramanian d8ae453fb9 Handle exempted layers (#983)
* WIP commit

* WIP commit

* Add tests

* remove debug
2022-09-05 18:42:59 +05:30
Raja Subramanian 26ba69c506 Log only on change and also don't log layer for audio (#934) 2022-08-20 10:04:21 +05:30
Raja Subramanian b5c023f986 Connection quality changes (#913)
* WIP commit

* Connection quality changes

- Fix Firefox showing poor quality
  o The issue was that we were using max available layer and
    calculating quality. The rationale being that even if
    server sends dynacast messages, client may not implement
    dynacast and still stream all layers. But, with Firefox
    (maybe a Firefox bug), it sends some small amount of
    data on layer 2 even when that layer is disabled.
    Guessing it is probing (or actually we might be using
    some small value for high layers as Firefox cannot turn off
    layers). That higher layer gets used in quality calculation.
    As the bit rate on that layer is extremely low, it yields low
    score.

    Fixed by considering the max expected layer. That is of most
    interest. Yes, clients may ignore dynacast and stream all layers,
    but, max expected is the one of interest. So, look for
    quality in the max expected layer and not max available layer.
- Lots of clean up around connection quality stuff
  o Use a dynamic scaling thing to ensure that we do not get bitten
    by absolute values. Calculate best possible scenario score and
    map that to maximum MOS score. This will ensure that different
    codecs, different settings do not mess up the scoring. For example,
    a client might use 1 Mbps for 720p, but a different client could
    use 2 Mbps for 720p. As an SFU/infrastructure middlebox, we do
    not have control over quality at those rates. We can only ensure
    that streaming happens smoothly at those rates. So, in that
    example, for client 1, 1 Mbps will map to MOS 5.0 and for client 2,
    2 Mbps will map to MOS 5.0. Any impairments after that will
    reflect in the score.
  o Penalise for missing target layer by one level for one layer missed.
  o Move tests to connection quality directory. The participant test
    was not super useful.

* Add missed file

* Remove debug code

* use more constants and initialise normalisation factor

* rtcscore pointer
2022-08-15 13:21:07 +05:30
Raja Subramanian 6b6f61b4df Adding transport fallback (#866)
* Adding transport fallback

Commented out for now so that we can gather some data.

* Promoting a few logs to info
2022-08-03 23:03:10 +05:30
David Zhao 53f51c8cb0 Logging cleanup (#843)
* Logging cleanup

Changes log levels to better match significance

* fix lock
2022-07-21 00:39:49 -07:00
Raja Subramanian 46bce33fb8 Cache and restore forwarder state on resume (#786)
* WIP commit

* Clean up

* spelling mistake

* Run subscribed track onBind in a go routine

* Address comments and more safety net

* Cache and restore forwarder state on resume

* conflicts

* mage generate
2022-06-24 22:02:03 +05:30
Raja Subramanian 87c8ec25b9 Check that max layers are valid before allowing overshoot. (#775) 2022-06-21 23:14:06 +05:30
Raja Subramanian 10b0c9b9ff Allow overshooting maximum when there are no bandwidth constraints. (#739)
* Allow overshooting maximum when there are no bandwidth constraints.

Some clients prioritize sending higher layer of video (for e.g.
Firefox). They may get into a state where congestion does not allow
sending lower layers.

That combined with adaptive streaming capping the max layer at a
certain level, it is possible to get into a state where video is
not streamed.

To make this experience better, allow overshoot beyond max layers
in case of optimal (i. e. no congestion) allocation.

NOTE: This means that the video could freeze when there is congestion
even if `AllowPause` is not disabled as in congested state, we do
not overshoot the max layer.

* log about allowing overshoot
2022-05-30 13:51:59 +05:30
cnderrauber f958fbcc1c simulcast codecs support (#720)
simulcast codecs support 

Co-authored-by: David Zhao <dz@livekit.io>
2022-05-27 19:55:50 +08:00
Raja Subramanian 9d0e4375f2 Use blank frames at frame rate (#710)
* Inject silence opus frames on mute.

If not, under certain circumstances, residual noise
seems to trigger comfort noise generation at the decoder
which is not all that comfortable.

* inject silence only when muting

* Add comment

* augment comment

* Delete blank line

* Adjust TS offset on blank frames

* Remove debug

* Do not modify `lastTS` as it affects timestamp on next switch.

* Trying more stuff for DTX

* - Use a go routine to send blank frames
- Use duration instead of number of frames and calculate number of
  frames

* augment comment

* Remove debug

* Return a chan from writeBlankFrameRTP

* Use a long duration for mute

* add comment

* Incorporate suggestion from Jie
2022-05-24 13:25:19 +05:30
Raja Subramanian a1e264bf34 Make a copy of available layers in forwarder. (#709)
Should be okay as that is usually only three elements max.

Stream tracker + manager send available layers. As stream trackers
run in different go routines, need to think some more about chances
of out-of-order operations. But, making a copy in forwarder so
that it is not referncing moving data.

Also, when setting up provisional allocation, make a copy
(that was the intention, i. e. a provisional allocation should have
stable data to work with).
2022-05-23 17:41:19 +05:30
Raja Subramanian d828e0fbd8 Inject silence opus frames on mute (#682)
* Inject silence opus frames on mute.

If not, under certain circumstances, residual noise
seems to trigger comfort noise generation at the decoder
which is not all that comfortable.

* inject silence only when muting

* Add comment

* augment comment

* Delete blank line

* Adjust TS offset on blank frames

* Remove debug

* Do not modify `lastTS` as it affects timestamp on next switch.

* use duration to calculate number of blank frames

* log errors in blank frames write path
2022-05-15 11:29:40 +05:30
cnderrauber 07b93e2e5b add support for av1 svc (#669)
* add support for av1 svc
2022-05-06 18:24:29 +08:00
Raja Subramanian 75ec31f237 Support starting off with not forwarding video (#623) 2022-04-19 12:37:53 +05:30
Raja Subramanian 93a2730128 Resync on mute to avoid sequence number jumps on unmute (#597) 2022-04-06 23:23:57 +05:30
Raja Subramanian 2e71fba3da Prevent negative timestamp diff (#595)
Found another reason for potential stalling on layer switch up.

When switching up, it is possible that the key frame of the packet
at higher layer arrives very close to a packet in the currently
forwarded layer.

An inversion happens when higher layer packet arrives earlier
(as timestamped at receicver), but gets scheduled for forwarding
later (as seen by forwarder).

Because of the order of processing goroutines,
it is possible to have negative diff when trying to adjust
RTP timestamps for layer switch. A negative diff results in
large jump in RTP timestamp. Client stalls, sends PLI three seconds
later (3 seconds is a Chrome thing, not sure about others), waits
for another key frame and starts again. In the mean time, the
video is frozen.
2022-04-06 10:18:41 +05:30
David Colburn 0b8a180554 Code inspection (#581)
* Code inspection

* fix [4]int64 conversiong
2022-03-30 13:49:53 -07:00
Raja Subramanian 641858832a Address edge case stream allocation (#544)
* Handle an edge in layer lock.

A very edge case
- Available layer: [0, 1, 2], but bitrate is not yet available.
We set it to layer 2 awaiting measurement.
- Measurement for layers 0 and 1 come through.
- Still no key frame for layer 2.
- Finalize layers runs and sees that bitrate is available for 0 and 1.
It finalizes layer 1.
- Layer 1 key frame comes (because we asked key frame of layer 2,
publisher sends key frame for all layers). Locks to layer 1.
- No more events happen to switch to layer 2.

Changes
-------
- Move bit rate measurement to StreamTrackerManager. Allows re-use
in relay.
- Make bit rate availability (from zero -> non-zero) an event
and let it flow through the stream allocation flow so that we
always have an event when bit rate measurement becomes available.
This gets rid of finalization which I was unhappy with it anyway as
it was polling every second.
- Removing REMB stuff from buffer. We do not use it.
It is incorrect anyway. REMB should be ay peer connection level.

* Fix test

* fix test

* Simplify allocate

* Simplify/clean up
2022-03-21 14:53:31 +05:30
Raja Subramanian 82e1c391a4 Fix time stamp jump on layer switch (#543) 2022-03-20 13:36:29 +05:30
Raja Subramanian 1d03a5a3b6 Lock temporal layers to target for non-temporal layer codecs also (#542) 2022-03-20 11:11:49 +05:30
Raja Subramanian dc6b3369f4 Minor clean up of unused stuff (#525) 2022-03-17 10:19:51 +05:30
Raja Subramanian 33f9726b79 Key frames (#522)
* Key frames

- Keep track of key frame stats
- Split out PLI from down track used for purpose of layer locking.
This will give us a good picture of down stream issues forcing a PLI.
- Use key frame requester whenever there is a layer lock required.
Not just the first key frame. With the synchronous thing, the counter
was just ridiculously high like 150 or something because of all
the initial padding packets. Also, use RTT in key frame requester.

* send first PLI before waiting

* Turn off key frame requester when disabled

* simplify
2022-03-16 19:55:12 +05:30
Raja Subramanian acbafa06f2 Log key frame and layer lock (#496) 2022-03-09 09:50:16 +05:30
Raja Subramanian 5a4181b581 Replacing hand rolled ion-sfu atomic with uber/atomic (#465)
* Replacing hand rolled ion-sfu atomic with uber/atomic

* Remove another hand rolled atomic
2022-02-25 11:57:09 +05:30
Raja Subramanian 92d47ec421 Resync uses SSRC change. Reset to 0 when a resync is needed. (#446) 2022-02-18 16:26:27 +05:30
Raja Subramanian d04f4d12d1 Throttle RTX under certain conditions to prevent RTX storm (#440)
* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* Clean up

* Remove debug

* Remove unneeded change

* fix test

* Remove incorrect comment

* WIP commit

* Reset probe after estimate trends down

* WIP commit

* variable name change

* Clean up

* Remove debug logs

* gofmt
2022-02-17 13:33:44 +05:30
Raja Subramanian 0bbed7f0bd Use padding for probing (#434)
* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* WIP commit

* Clean up

* Remove debug

* Remove unneeded change

* fix test

* Remove incorrect comment

* Reset probe after estimate trends down
2022-02-17 11:03:23 +05:30
cnderrauber 32d8af6da0 repeat request pli until first keyframe received (#436) 2022-02-16 19:57:55 +08:00
Raja Subramanian c9cfb0d362 Need to return delta the new provisional layer takes. (#433) 2022-02-11 14:04:47 +05:30
Raja Subramanian a6338992e8 Stop forwarding on congestion (#429)
* WIP commit

* comment out debug stuff
2022-02-11 09:17:53 +05:30
David Colburn 7bbd238188 clean up logs and imports (#400) 2022-02-03 14:20:19 -07:00
Raja Subramanian e22f47b416 Split out stream tracker manager (#394)
* Random clean up

* Split out StreamTrackerManager for re-use

* Reset the correct tracker

* use generation counter to exit coroutine

* start only for video and when enabled

* Add RemoveAllTrackers method
2022-02-01 13:24:42 +05:30
Raja Subramanian 745939ec24 Smoother dynacast transition (#390) 2022-01-31 07:47:24 +05:30
Raja Subramanian a1f88faed1 Add a resync API to sfu.DownTrack (#389)
* Add a resync API to sfu.DownTrack

Also passing in logger with context into sfu package. More to do here
with proper logging context in all modules, but this is a start

* Remove debug code

* fix tests
2022-01-30 10:59:47 +05:30
David Colburn 5bea9debb7 Code cleanup (#353) 2022-01-19 02:13:06 -08:00
Raja Subramanian 017ed13338 Prevent multiple resume notifications on track (#334)
* Prevent multiple resume notifications on track

When returning previous allocation as is, reset change to none.
Ideally, would like to have change as a separate return and not in last
allocation. But, also prefer to have last allocation state. For now,
resetting change.

* log bandwidth estimate only on decrease
2022-01-12 23:19:56 +05:30
Raja Subramanian 8d0fb179a0 Layer 0 and non-simulacst tracks also can be fully unsubscribed. (#308) 2021-12-31 14:04:22 +05:30
Raja Subramanian 98586c2490 A simple configuration for congestion control. (#305) 2021-12-31 00:26:29 +05:30
David Colburn 0b71a46239 missed some typos 2021-12-17 13:25:41 -08:00
David Colburn faa870de3d Move callbacks out of messageRouter (#269)
* move callbacks out of messageRouter

* OCD

* more OCD

* fix forwarder test

* even more OCD

* maximum OCD

* package name collision, copy lock by value
2021-12-17 13:19:23 -08:00
cnderrauber a06edd885e fix panic in forwarder (#268)
Co-authored-by: cnderrauber <zengjie9004@gmail.com>
2021-12-17 23:51:06 +08:00
Raja Subramanian 502c57d787 Fix forwarding status deduction (#267)
* Fix forwarding status deduction

- When muted OR when there are no available layers, declare optimal
- When target layer is the maximum it can achieve taking available
  layers into account even if they are not the maximum subscribed layer,
  it is still optimal as there is nothing better available.

* Fix and add more tests for forwarding status
2021-12-17 15:45:04 +05:30
Raja Subramanian e504b6678c Deficient state handling when a track needs a change (#261)
* WIP commit

* deficient handling

* Add missing ProvisionalAllocatePrepare

* adjust state on track removal

* Increase test timeout

* - Add comments about cooperative routines
- Take down transition if available in cooperative scheme
- Use layer comparison when taking down transition. Because of when the
  bitrate is measured, it is not always guaranteed bandwidthDelta is -ve
  when moving down.
- Do not add track to stream allocator till bind.

* make comment better

* a bit more clear comments

* Use OnBind on subscribed track
2021-12-16 10:58:34 +05:30
Raja Subramanian e54ce4f674 Stream Allocator Try 3 (#257)
* Stream Allocator Try 3

Making an intermediate PR to do
- Special treatment for screen share tracks
- When allocating all tracks,
  o try to stream all tracks by starting with the lowest layer
  o multi-pass across tracks to get a more even distribution

Not yet done:
-------------
In deficient state,
o Allocate a specific track on a change
o Steal from other tracks

* Correct sense of managed track

* have to range to copy

* generate

* fix VideoLayers compare

* Use t.simulcasted
2021-12-14 12:48:09 +05:30