Skip to content

Commit

Permalink
[android] Refine video render algorithm
Browse files Browse the repository at this point in the history
1. Improve the precision of timestamp conversion.
2. Set default playback rate to 0 in AudioFrameTracker.

b/332858454
  • Loading branch information
jasonzhangxx committed May 16, 2024
1 parent 73d21d1 commit 9cb954a
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ public long adjustReleaseTime(
adjustedFrameTimeNs = candidateAdjustedFrameTimeNs;
adjustedReleaseTimeNs =
syncUnadjustedReleaseTimeNs
+ (long) ((adjustedFrameTimeNs - syncFramePresentationTimeNs) / playbackRate);
+ adjustFrameTimeForPlaybackRate(
adjustedFrameTimeNs - syncFramePresentationTimeNs, playbackRate);
}
} else {
// We're synced but haven't waited the required number of frames to apply an adjustment.
Expand Down Expand Up @@ -199,10 +200,20 @@ protected void onSynced() {
private boolean isDriftTooLarge(long frameTimeNs, long releaseTimeNs, double playbackRate) {
long elapsedFrameTimeNs = frameTimeNs - syncFramePresentationTimeNs;
long elapsedReleaseTimeNs = releaseTimeNs - syncUnadjustedReleaseTimeNs;
return Math.abs(elapsedReleaseTimeNs - elapsedFrameTimeNs / playbackRate)
return Math.abs(
elapsedReleaseTimeNs - adjustFrameTimeForPlaybackRate(elapsedFrameTimeNs, playbackRate))
> MAX_ALLOWED_DRIFT_NS;
}

private long adjustFrameTimeForPlaybackRate(long frameTimeNs, double playbackRate) {
// We support playback rate of {0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2}. So, we use a multiplier
// of 100
// here to keep precision of the timestamp conversion.
final long PLAYBACK_RATE_ADJUSTMENT_MULTIPLIER = 100;
long multipliedPlaybackRate = (long) (playbackRate * PLAYBACK_RATE_ADJUSTMENT_MULTIPLIER);
return frameTimeNs / multipliedPlaybackRate * PLAYBACK_RATE_ADJUSTMENT_MULTIPLIER;
}

private static long closestVsync(long releaseTime, long sampledVsyncTime, long vsyncDuration) {
long vsyncCount = (releaseTime - sampledVsyncTime) / vsyncDuration;
long snappedTimeNs = sampledVsyncTime + (vsyncDuration * vsyncCount);
Expand Down
7 changes: 3 additions & 4 deletions starboard/android/shared/video_render_algorithm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void VideoRenderAlgorithm::Render(
double playback_rate;
int64_t playback_time = media_time_provider->GetCurrentMediaTime(
&is_audio_playing, &is_audio_eos_played, &is_underflow, &playback_rate);
if (!is_audio_playing) {
if (!is_audio_playing || playback_rate == 0.0) {
break;
}
if (playback_rate != playback_rate_) {
Expand All @@ -91,8 +91,8 @@ void VideoRenderAlgorithm::Render(
}
}

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

auto system_time_ns = GetSystemNanoTime();
auto unadjusted_frame_release_time_ns = system_time_ns + (early_us * 1000);
Expand All @@ -101,7 +101,6 @@ void VideoRenderAlgorithm::Render(
video_frame_release_time_helper_.AdjustReleaseTime(
frames->front()->timestamp(), unadjusted_frame_release_time_ns,
playback_rate);

early_us = (adjusted_release_time_ns - system_time_ns) / 1000;

if (early_us < kBufferTooLateThreshold) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class AudioFrameTracker {
// Usually there are very few elements, so std::vector<> is efficient enough.
std::vector<FrameRecord> frame_records_;
int64_t frames_played_adjusted_to_playback_rate_ = 0;
double last_playback_rate_ = 1.0;
double last_playback_rate_ = 0.0;
};

} // namespace filter
Expand Down
3 changes: 3 additions & 0 deletions starboard/shared/starboard/player/player_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ struct SbPlayerPrivate {
#else // SB_API_VERSION >= 15
void GetInfo(SbPlayerInfo2* out_player_info);
#endif // SB_API_VERSION >= 15

// TODO: this function is not used.
void SetPause(bool pause);

void SetPlaybackRate(double playback_rate);
void SetVolume(double volume);

Expand Down

0 comments on commit 9cb954a

Please sign in to comment.