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

Cherry pick PR #3136: [android] Support playback rate in VideoRendererAlgorithm #3149

Merged
merged 1 commit into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public final class VideoFrameReleaseTimeHelper {
private long lastFramePresentationTimeUs;
private long adjustedLastFrameTimeNs;
private long pendingAdjustedFrameTimeNs;
private double lastPlaybackRate;

private boolean haveSync;
private long syncUnadjustedReleaseTimeNs;
Expand Down Expand Up @@ -93,6 +94,7 @@ private VideoFrameReleaseTimeHelper(double defaultDisplayRefreshRate) {
@UsedByNative
public void enable() {
haveSync = false;
lastPlaybackRate = -1;
if (useDefaultDisplayVsync) {
vsyncSampler.addObserver();
}
Expand All @@ -118,7 +120,17 @@ public void disable() {
*/
@SuppressWarnings("unused")
@UsedByNative
public long adjustReleaseTime(long framePresentationTimeUs, long unadjustedReleaseTimeNs) {
public long adjustReleaseTime(
long framePresentationTimeUs, long unadjustedReleaseTimeNs, double playbackRate) {
if (playbackRate == 0) {
return unadjustedReleaseTimeNs;
}
if (playbackRate != lastPlaybackRate) {
// Resync if playback rate has changed.
haveSync = false;
lastPlaybackRate = playbackRate;
}

long framePresentationTimeNs = framePresentationTimeUs * 1000;

// Until we know better, the adjustment will be a no-op.
Expand All @@ -140,18 +152,18 @@ public long adjustReleaseTime(long framePresentationTimeUs, long unadjustedRelea
(framePresentationTimeNs - syncFramePresentationTimeNs) / frameCount;
// Project the adjusted frame time forward using the average.
long candidateAdjustedFrameTimeNs = adjustedLastFrameTimeNs + averageFrameDurationNs;

if (isDriftTooLarge(candidateAdjustedFrameTimeNs, unadjustedReleaseTimeNs)) {
if (isDriftTooLarge(candidateAdjustedFrameTimeNs, unadjustedReleaseTimeNs, playbackRate)) {
haveSync = false;
} else {
adjustedFrameTimeNs = candidateAdjustedFrameTimeNs;
adjustedReleaseTimeNs =
syncUnadjustedReleaseTimeNs + adjustedFrameTimeNs - syncFramePresentationTimeNs;
syncUnadjustedReleaseTimeNs
+ (long) ((adjustedFrameTimeNs - syncFramePresentationTimeNs) / playbackRate);
}
} else {
// We're synced but haven't waited the required number of frames to apply an adjustment.
// Check drift anyway.
if (isDriftTooLarge(framePresentationTimeNs, unadjustedReleaseTimeNs)) {
if (isDriftTooLarge(framePresentationTimeNs, unadjustedReleaseTimeNs, playbackRate)) {
haveSync = false;
}
}
Expand Down Expand Up @@ -184,10 +196,11 @@ protected void onSynced() {
// Do nothing.
}

private boolean isDriftTooLarge(long frameTimeNs, long releaseTimeNs) {
private boolean isDriftTooLarge(long frameTimeNs, long releaseTimeNs, double playbackRate) {
long elapsedFrameTimeNs = frameTimeNs - syncFramePresentationTimeNs;
long elapsedReleaseTimeNs = releaseTimeNs - syncUnadjustedReleaseTimeNs;
return Math.abs(elapsedReleaseTimeNs - elapsedFrameTimeNs) > MAX_ALLOWED_DRIFT_NS;
return Math.abs(elapsedReleaseTimeNs - elapsedFrameTimeNs / playbackRate)
> MAX_ALLOWED_DRIFT_NS;
}

private static long closestVsync(long releaseTime, long sampledVsyncTime, long vsyncDuration) {
Expand Down
13 changes: 8 additions & 5 deletions starboard/android/shared/video_render_algorithm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,16 @@ void VideoRenderAlgorithm::Render(
}
}

jlong early_us = frames->front()->timestamp() - playback_time;
jlong early_us = (frames->front()->timestamp() - playback_time) /
(playback_rate != 0 ? playback_rate : 1);

auto system_time_ns = GetSystemNanoTime();
auto unadjusted_frame_release_time_ns = system_time_ns + (early_us * 1000);

auto adjusted_release_time_ns =
video_frame_release_time_helper_.AdjustReleaseTime(
frames->front()->timestamp(), unadjusted_frame_release_time_ns);
frames->front()->timestamp(), unadjusted_frame_release_time_ns,
playback_rate);

early_us = (adjusted_release_time_ns - system_time_ns) / 1000;

Expand Down Expand Up @@ -149,12 +151,13 @@ VideoRenderAlgorithm::VideoFrameReleaseTimeHelper::

jlong VideoRenderAlgorithm::VideoFrameReleaseTimeHelper::AdjustReleaseTime(
jlong frame_presentation_time_us,
jlong unadjusted_release_time_ns) {
jlong unadjusted_release_time_ns,
double playback_rate) {
SB_DCHECK(j_video_frame_release_time_helper_);
auto* env = JniEnvExt::Get();
return env->CallLongMethodOrAbort(
j_video_frame_release_time_helper_, "adjustReleaseTime", "(JJ)J",
frame_presentation_time_us, unadjusted_release_time_ns);
j_video_frame_release_time_helper_, "adjustReleaseTime", "(JJD)J",
frame_presentation_time_us, unadjusted_release_time_ns, playback_rate);
}

} // namespace shared
Expand Down
3 changes: 2 additions & 1 deletion starboard/android/shared/video_render_algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class VideoRenderAlgorithm : public ::starboard::shared::starboard::player::
VideoFrameReleaseTimeHelper();
~VideoFrameReleaseTimeHelper();
jlong AdjustReleaseTime(jlong frame_presentation_time_us,
jlong unadjusted_release_time_ns);
jlong unadjusted_release_time_ns,
double playback_rate);

private:
jobject j_video_frame_release_time_helper_ = nullptr;
Expand Down
Loading