diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java b/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java index e334a3d2a7e1..50d1bb9e73dc 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java @@ -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. @@ -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); diff --git a/starboard/android/shared/video_render_algorithm.cc b/starboard/android/shared/video_render_algorithm.cc index 4b650141fb21..a319162c3c57 100644 --- a/starboard/android/shared/video_render_algorithm.cc +++ b/starboard/android/shared/video_render_algorithm.cc @@ -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_) { @@ -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); @@ -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) { diff --git a/starboard/shared/starboard/player/filter/audio_frame_tracker.h b/starboard/shared/starboard/player/filter/audio_frame_tracker.h index 4582a7421408..1de3a96e4ddd 100644 --- a/starboard/shared/starboard/player/filter/audio_frame_tracker.h +++ b/starboard/shared/starboard/player/filter/audio_frame_tracker.h @@ -54,7 +54,7 @@ class AudioFrameTracker { // Usually there are very few elements, so std::vector<> is efficient enough. std::vector 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 diff --git a/starboard/shared/starboard/player/player_internal.h b/starboard/shared/starboard/player/player_internal.h index e58c668d6388..ec7f233ac4a1 100644 --- a/starboard/shared/starboard/player/player_internal.h +++ b/starboard/shared/starboard/player/player_internal.h @@ -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);