Skip to content
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

Issue 688: FEC estimates block duration #717

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

baranovmv
Copy link
Member

@baranovmv baranovmv commented Apr 28, 2024

Reader and writer esimate duration of
FEC block in ns as this value could vary
even though number of packets is known.
For now it is decided to keep the greates
value seen in the current session, not
average.

#688

@baranovmv baranovmv requested a review from gavv April 28, 2024 17:35
@github-actions github-actions bot added the ready for review Pull request can be reviewed label Apr 28, 2024
Copy link

🤖 Upon creation, pull request description does not have a link to an issue. If there is a related issue, please add it to the description using any of the supported formats.

@baranovmv baranovmv changed the title FEC estimates block duration Issue 688: FEC estimates block duration May 6, 2024
@github-actions github-actions bot added the needs rebase Pull request has conflicts and should be rebased label May 10, 2024
Copy link

🤖 The latest upstream change made this pull request unmergeable. Please resolve the merge conflicts.

Comment on lines 106 to 112
bool LatencyMonitor::pre_process_(const Frame& frame) {
if (fec_reader_) {
latency_metrics_.fec_block_duration =
packet_sample_spec_.stream_timestamp_2_ns(fec_reader_->max_block_duration());
} else {
latency_metrics_.fec_block_duration = 0;
}
Copy link
Member

Choose a reason for hiding this comment

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

In LatencyMonitor::read, we have:

        compute_niq_latency_();
        query_link_meter_();

        if (!pre_process_(frame)) {
            alive_ = false;
        }

All metrics except fec_block_duration are filled before calling pre-process. So for consistency, I suggest to add a method like query_fec_reader() and also call it there.

Comment on lines 144 to 150
if (next_packet_ == 0) {
if (pp) {
update_block_duration_(pp);
} else {
prev_block_timestamp_valid_ = false;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

So this is triggered when the very first packet of a block is received.

What about moving this logic to next_block_()?

It is triggered when we're going to switch to the next block.

Inside next_block_(), even if the first packet was lost, there is the maximum chance that it was repaired.

Comment on lines 808 to 809
if (!ptr->rtp()) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

Let's use Packet::stream_timestamp() instead of Packet::rtp(), this way fec::Reader will continue to be RTP-independent.

block_dur = packet::stream_timestamp_diff(ptr->rtp()->stream_timestamp,
prev_block_timestamp_);
}
roc_panic_if_msg(block_dur < 0, "fec reader: negative block duration");
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 panic is not appropriate here, because corrupted/malformed packets would lead to a crash?

Instead we can skip the check. Probably also log to LogTrace.

prev_block_timestamp_);
}
roc_panic_if_msg(block_dur < 0, "fec reader: negative block duration");
block_max_duration_ = std::max(block_max_duration_, block_dur);
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't we compute maximum in LatencyTuner instead of fec::Reader? And report only immediate value from fec::Reader?

Why:

  • Most likely we want running maximum instead of total maxium. Maybe at least in later versions. But this kind of details (running window, etc) should belong to LatencyTuner?

  • This logic (running max) would probably be the same for sender & receiver.

Copy link
Member Author

Choose a reason for hiding this comment

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

With the manner the metrics are passed into tuner, it would be difficult to be sure that it has updates of fec block duration on every new block arrived. And this could potentially lead to wrong estimation of maximum.

Copy link
Member

Choose a reason for hiding this comment

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

Fair enough.

Copy link
Member

Choose a reason for hiding this comment

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

Hm, given it one more thought, this is probably not the case.

While latency tuner updates FE with some big period, like 200ms, latency monitor and feedback monitor are invoked every frame.

And, while user is allowed to read and write big frames, top-level pipeline code will anyway split them in smaller frames (to ensure that we don't block in processing for long time and that frames can fit max size of pool buffer).

So in practice all pipeline components are invoked with small frames (e.g. 1ms), much lower than FEC block size, and I think in our design (in general) we can assume that it's always true, because it simplifies many things.

For example, we already do the same with incoming queue - we're sampling it's size every frame. I think we in general can sample anything per frame.

So I guess you can just sample FEC block duration in LatencyMonitor::read?

@@ -109,6 +114,7 @@ status::StatusCode Writer::write(const packet::PacketPtr& pp) {
}

if (cur_packet_ == 0) {
update_block_duration_(pp);
Copy link
Member

Choose a reason for hiding this comment

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

I suggest to call this from begin_block_ or end_block_ - so that everything called on block boundary would be in same place.

if (!ptr->rtp()) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

Same comment about rtp().

Copy link
Member

Choose a reason for hiding this comment

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

Can we create a separate set of tests for block_duration feature?

This feature feels pretty isolated from the main "purpose" of fec::Reader (repairing packets) and I think the story of its test is a bit different from story of the rest tests.

The story of original tests goes from simpler to more complicated, starting from one block, then introducing a loss, then switching to multiple blocks, introducing more losses, reordering, etc.

The story of block_duration tests I think should include:

  • good case
  • lost first packet of first block
  • lost first packet of non-first block
  • lost packet inside block (maybe even everything except first packet)
  • lost whole block (in other words, switched to other block)
  • resizing block (look at other resize_xxx tests for an example)

Sorry for complicating your life, but fec reader & writer are so complicated that I think having so many tests for every feature is worth it.

@gavv gavv added needs revision Pull request should be revised by its author and removed ready for review Pull request can be reviewed labels May 12, 2024
Reader and writer esimate duration of
FEC block in ns as this value could vary
even though number of packets is known.
For now it is decided to keep the greates
value seen in the current session, not
average.
@github-actions github-actions bot removed the needs rebase Pull request has conflicts and should be rebased label May 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs revision Pull request should be revised by its author
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants