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

SntpClient periodically re-syncs the offset to NTP server #1794

Merged

Conversation

stevemayhew
Copy link
Contributor

This is the equivalent pull request to #697, just rebased (with simple conflict resolve) to the main branch.

@marcbaechinger feel free to pick one and close the other.

Many of the Android TV platforms do not report accurate `SystemClock.elapsedRealtime()`
In addition this drift is not consistant accross multiple boxes, so the time offset
between any pair of boxes will vary over time.

This variance will lead to a drift in the Live Offset calculation.

Fix is simple, inValidate the NTP server query after a period of time (10 minutes)
and re-issue the call
@marcbaechinger
Copy link
Contributor

marcbaechinger commented Oct 14, 2024

This looks good to me as in how this would work regarding reinitialization. Many thanks, Steve.

I was wondering whether we want to use C.TIME_UNSET to never reinitialize as a default. Mainly to not change the behaviour of DashMediaSource without opting in. Then we could do such a getter similar to those for timeout and sntp host to allow opt-in in.

We would then wouldn't need to discuss how you came to choose 10 minutes as a default. :)

You as a user could then opt-in once at app level using the SntpClient API? I'm not really convinced. However, the static design of that client makes it a bit difficult to provide an API that could be enabled on a media source level or similar. SntpClient being a proper object instance would probably be the right thing to do.

How does adding a getter to override the default sound to you?

Copy link
Contributor

@marcbaechinger marcbaechinger left a comment

Choose a reason for hiding this comment

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

As mentioned in the main comment. Consider adding a getter to override the default of C.TIME_UNSET and disable reinitialization for C.TIME_UNSET?

@@ -49,6 +49,9 @@ public final class SntpClient {
/** The default maximum time, in milliseconds, to wait for the SNTP request to complete. */
public static final int DEFAULT_TIMEOUT_MS = 1_000;

/** Max time to allow before re-initializing with NTP server, default is 10 minutes */
private static final long MAX_ELAPSED_MS_TILL_UPDATE = 60 * 10 * 1_000L;
Copy link
Contributor

Choose a reason for hiding this comment

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

UNTIL ? :)

Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned in the PR comment. Is this a value that comes from your experience when operating live streams? I'm mostly curious...

@nikitapn
Copy link

nikitapn commented Oct 15, 2024

This is what we also need, but could you remove hardcoded MAX_ELAPSED_MS_TILL_UPDATE?

From our experience with media boxes that we have, the sync interval of 12 hours is adequate.
We have some statistics gathered from deltas of offsets after some time. In our case, the drift is ~0.2 seconds per 12 hours. So we would like to decide sync interval for ourselves by having a setter.
Also Android OS only does "a single time query approximately once a day" , and frequent NTP sync might possibly affect zap time every 10 minutes user switches a channel.
Thanks.

@stevemayhew
Copy link
Contributor Author

Having it default to original behavior with a setter to enable the refresh (and set the time) sounds fine to me. It is possible this issue is limited to Android Streamers as phones likely time sync with the carrier.

Also, for phones issuing the network request has at least some small battery penalty

Feel free to add the commit with the change, you should have push access to the repo

@marcbaechinger
Copy link
Contributor

Ok, thanks! Will proceed that way.

@marcbaechinger
Copy link
Contributor

I pushed a commit with the getter and the release notes. I'm going to send this for internal review now. You may see some more commits being added as I make changes in response to review feedback. Please refrain from pushing any more substantive changes as it will complicate the internal review.

Let me know if you see something, Steve. Else I proceed as described above. Thanks again!

@stevemayhew
Copy link
Contributor Author

stevemayhew commented Oct 22, 2024 via email

@marcbaechinger
Copy link
Contributor

marcbaechinger commented Oct 23, 2024

@stevemayhew @nikitapn

I have that CL ready for submission (see commits in this PR).

May I ask you both how you are going to use that feature? Are you having your own media source that is using the client? I'm asking because when used with DashMediaSource then loadNtpTimeOffset() is called in [1]. If that succeeds the callback will set elapsedRealtimeOffsetMs in [2].

Once elapsedRealtimeOffsetMs is set it will be used in the if expression that would call the SntpClient if it was C.TIME_UNSET. But once set by SntpClient it never passes that expression inn [3].

Is the use case for this change usage in DashMediaSource or are you having your own media source?

[1] https://github.com/androidx/media/blob/release/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java#L715
[2] https://github.com/androidx/media/blob/release/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java#L863
[3] https://github.com/androidx/media/blob/release/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java#L710

@nikitapn
Copy link

nikitapn commented Oct 23, 2024

In our case, users experience the issue when they bring the media box out of standby mode. During this process, we recreate the player (our wrapper with all the stuff) completely because the instance has been destroyed before entering standby, and elapsedRealtimeOffsetMs will be TIME_UNSET in the new DashMediaSource instance.

I suspect we may still encounter some problems when users have been watching a live stream without turning the box off for a few weeks, right? In my opinion, this is a rare situation.

@marcbaechinger
Copy link
Contributor

Ah, I see. Yeah, obviously. Thanks for clarifying. I didn''t realized that it wouldn't re-initialize even when a new source is created. This case can be handled with this change as you say. The design of that SntpClient class with these static methods is, lets say, peculiar. But yeah, what you saying makes totally sense! Thanks!

Will submit as it is. If we need to enable this re-initialization inside the same DashMediaSource instance, we can look into this again.

@copybara-service copybara-service bot merged commit b5615d5 into androidx:main Oct 23, 2024
1 check passed
ivanbuper pushed a commit that referenced this pull request Nov 5, 2024
PiperOrigin-RevId: 689121191
(cherry picked from commit b5615d5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants