From b1cd52bc58b3dfd02dab4784ea423ebddae874c4 Mon Sep 17 00:00:00 2001 From: Olivier Bouillet <62574056+freeboub@users.noreply.github.com> Date: Wed, 8 May 2024 17:55:35 +0200 Subject: [PATCH] fix(android): video flickering add playback start (#3746) * perf: ensure we do not provide callback to native if no callback provided from app * chore: rework bufferConfig to make it more generic and reduce ReactExoplayerView code size * fix(android): avoid video flickering at playback start --- .../brentvatne/exoplayer/ExoPlayerView.java | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java index db56f65659..41036a7192 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java @@ -1,13 +1,12 @@ package com.brentvatne.exoplayer; import android.content.Context; + +import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.media3.common.AdViewProvider; import androidx.media3.common.C; -import androidx.media3.common.PlaybackException; -import androidx.media3.common.PlaybackParameters; import androidx.media3.common.Player; -import androidx.media3.common.Timeline; import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.Cue; @@ -38,8 +37,8 @@ public final class ExoPlayerView extends FrameLayout implements AdViewProvider { private final AspectRatioFrameLayout layout; private final ComponentListener componentListener; private ExoPlayer player; - private Context context; - private ViewGroup.LayoutParams layoutParams; + final private Context context; + final private ViewGroup.LayoutParams layoutParams; private final FrameLayout adOverlayFrameLayout; private boolean useTextureView = true; @@ -113,7 +112,7 @@ public boolean isPlaying() { } public void setSubtitleStyle(SubtitleStyle style) { - // ensure we reset subtile style before reapplying it + // ensure we reset subtitle style before reapplying it subtitleLayout.setUserDefaultStyle(); subtitleLayout.setUserDefaultTextSize(); @@ -211,16 +210,6 @@ public void setResizeMode(@ResizeMode.Mode int resizeMode) { } } - /** - * Get the view onto which video is rendered. This is either a {@link SurfaceView} (default) - * or a {@link TextureView} if the {@code use_texture_view} view attribute has been set to true. - * - * @return either a {@link SurfaceView} or a {@link TextureView}. - */ - public View getVideoSurfaceView() { - return surfaceView; - } - public void setUseTextureView(boolean useTextureView) { if (useTextureView != this.useTextureView) { this.useTextureView = useTextureView; @@ -263,15 +252,24 @@ private void updateForCurrentTrackSelections() { shutterView.setVisibility(this.hideShutterView ? View.INVISIBLE : View.VISIBLE); } + Runnable hideShutterViewRunnable = new Runnable() { + @Override + public void run() { + shutterView.setVisibility(INVISIBLE); + } + }; + public void invalidateAspectRatio() { // Resetting aspect ratio will force layout refresh on next video size changed layout.invalidateAspectRatio(); + + removeCallbacks(hideShutterViewRunnable); } private final class ComponentListener implements Player.Listener { @Override - public void onCues(List cues) { + public void onCues(@NonNull List cues) { subtitleLayout.setCues(cues); } @@ -288,11 +286,16 @@ public void onVideoSizeChanged(VideoSize videoSize) { @Override public void onRenderedFirstFrame() { - shutterView.setVisibility(INVISIBLE); + // The shutter view is use to hide dirty resizing issue when starting playback. + // In case video doesn't match your View aspect ratio, at playback startup you may have flickering during resize. + // we saw that onRenderedFirstFrame is called before first resizing + // Then hiding the shutterView directly may not hide the flickering. + // This small delay avoid the flickering + postDelayed(hideShutterViewRunnable, 15); } @Override - public void onTracksChanged(Tracks tracks) { + public void onTracksChanged(@NonNull Tracks tracks) { updateForCurrentTrackSelections(); } }