Move VideoComponent in ExoPlayer

VideoFrameMetadataListener and CameraMotionListener are still part
of the Player interface as a good way to break the UI dependency
on them has not yet been finalised.

PiperOrigin-RevId: 368863829
This commit is contained in:
krocard 2021-04-16 17:37:28 +01:00 committed by Oliver Woodman
parent a6e9a9c6d2
commit cdebf6c68b
12 changed files with 501 additions and 217 deletions

View File

@ -3,6 +3,11 @@
### dev-v2 (not yet released)
* Core Library:
* Move `Player` components to `ExoPlayer`. For example
`Player.VideoComponent` is now `ExoPlayer.VideoComponent`.
* The most used methods of `Player`'s audio/video/text/metadata components
have been added to `Player`. Support can be queried using
`Player.isCommandAvailable` instead of testing for component nullness.
* Add position info of the old and the new position as arguments to
`EventListener.onPositionDiscontinuity`. Add the new reasons
`DISCONTINUITY_REASON_SKIP` and `DISCONTINUITY_REASON_REMOVE` and rename

View File

@ -25,8 +25,8 @@ import android.os.Handler;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.android.exoplayer2.util.TimedValueQueue;
@ -72,7 +72,7 @@ public final class VideoProcessingGLSurfaceView extends GLSurfaceView {
@Nullable private SurfaceTexture surfaceTexture;
@Nullable private Surface surface;
@Nullable private Player.VideoComponent videoComponent;
@Nullable private ExoPlayer.VideoComponent videoComponent;
/**
* Creates a new instance. Pass {@code true} for {@code requireSecureContext} if the {@link
@ -151,7 +151,7 @@ public final class VideoProcessingGLSurfaceView extends GLSurfaceView {
*
* @param newVideoComponent The new video component, or {@code null} to detach this view.
*/
public void setVideoComponent(@Nullable Player.VideoComponent newVideoComponent) {
public void setVideoComponent(@Nullable ExoPlayer.VideoComponent newVideoComponent) {
if (newVideoComponent == videoComponent) {
return;
}

View File

@ -19,6 +19,10 @@ import static com.google.android.exoplayer2.util.Util.castNonNull;
import static java.lang.Math.min;
import android.os.Looper;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.BasePlayer;
@ -44,6 +48,8 @@ import com.google.android.exoplayer2.util.ListenerSet;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
import com.google.android.gms.cast.CastStatusCodes;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaQueueItem;
@ -276,12 +282,6 @@ public final class CastPlayer extends BasePlayer {
// Player implementation.
@Override
@Nullable
public VideoComponent getVideoComponent() {
return null;
}
@Override
public Looper getApplicationLooper() {
return Looper.getMainLooper();
@ -653,6 +653,57 @@ public final class CastPlayer extends BasePlayer {
return 1;
}
/** This method is not supported and does nothing. */
@Override
public void setVideoFrameMetadataListener(VideoFrameMetadataListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoFrameMetadataListener(VideoFrameMetadataListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void setCameraMotionListener(CameraMotionListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void clearCameraMotionListener(CameraMotionListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurface() {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurface(@Nullable Surface surface) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoSurface(@Nullable Surface surface) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoSurfaceView(@Nullable SurfaceView surfaceView) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoTextureView(@Nullable TextureView textureView) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoTextureView(@Nullable TextureView textureView) {}
/** This method is not supported and returns an empty list. */
@Override
public ImmutableList<Cue> getCurrentCues() {

View File

@ -37,7 +37,6 @@ import com.google.android.exoplayer2.Player.TimelineChangeReason;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.util.ErrorMessageProvider;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoListener;
/** Leanback {@code PlayerAdapter} implementation for {@link Player}. */
public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnable {
@ -49,7 +48,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
private final Context context;
private final Player player;
private final Handler handler;
private final ComponentListener componentListener;
private final PlayerListener playerListener;
private final int updatePeriodMs;
@Nullable private PlaybackPreparer playbackPreparer;
@ -73,7 +72,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
this.player = player;
this.updatePeriodMs = updatePeriodMs;
handler = Util.createHandlerForCurrentOrMainLooper();
componentListener = new ComponentListener();
playerListener = new PlayerListener();
controlDispatcher = new DefaultControlDispatcher();
}
@ -118,23 +117,15 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
public void onAttachedToHost(PlaybackGlueHost host) {
if (host instanceof SurfaceHolderGlueHost) {
surfaceHolderGlueHost = ((SurfaceHolderGlueHost) host);
surfaceHolderGlueHost.setSurfaceHolderCallback(componentListener);
surfaceHolderGlueHost.setSurfaceHolderCallback(playerListener);
}
notifyStateChanged();
player.addListener(componentListener);
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.addVideoListener(componentListener);
}
player.addListener(playerListener);
}
@Override
public void onDetachedFromHost() {
player.removeListener(componentListener);
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.removeVideoListener(componentListener);
}
player.removeListener(playerListener);
if (surfaceHolderGlueHost != null) {
removeSurfaceHolderCallback(surfaceHolderGlueHost);
surfaceHolderGlueHost = null;
@ -227,10 +218,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
/* package */ void setVideoSurface(@Nullable Surface surface) {
hasSurface = surface != null;
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.setVideoSurface(surface);
}
player.setVideoSurface(surface);
maybeNotifyPreparedStateChanged(getCallback());
}
@ -258,8 +246,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
surfaceHolderGlueHost.setSurfaceHolderCallback(null);
}
private final class ComponentListener
implements Player.EventListener, SurfaceHolder.Callback, VideoListener {
private final class PlayerListener implements Player.Listener, SurfaceHolder.Callback {
// SurfaceHolder.Callback implementation.

View File

@ -67,146 +67,6 @@ import java.util.List;
*/
public interface Player {
/** The video component of a {@link Player}. */
interface VideoComponent {
/**
* Sets the {@link C.VideoScalingMode}.
*
* @param videoScalingMode The {@link C.VideoScalingMode}.
*/
void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode);
/** Returns the {@link C.VideoScalingMode}. */
@C.VideoScalingMode
int getVideoScalingMode();
/**
* Adds a listener to receive video events.
*
* @param listener The listener to register.
*/
void addVideoListener(VideoListener listener);
/**
* Removes a listener of video events.
*
* @param listener The listener to unregister.
*/
void removeVideoListener(VideoListener listener);
/**
* Sets a listener to receive video frame metadata events.
*
* <p>This method is intended to be called by the same component that sets the {@link Surface}
* onto which video will be rendered. If using ExoPlayer's standard UI components, this method
* should not be called directly from application code.
*
* @param listener The listener.
*/
void setVideoFrameMetadataListener(VideoFrameMetadataListener listener);
/**
* Clears the listener which receives video frame metadata events if it matches the one passed.
* Else does nothing.
*
* @param listener The listener to clear.
*/
void clearVideoFrameMetadataListener(VideoFrameMetadataListener listener);
/**
* Sets a listener of camera motion events.
*
* @param listener The listener.
*/
void setCameraMotionListener(CameraMotionListener listener);
/**
* Clears the listener which receives camera motion events if it matches the one passed. Else
* does nothing.
*
* @param listener The listener to clear.
*/
void clearCameraMotionListener(CameraMotionListener listener);
/**
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
* currently set on the player.
*/
void clearVideoSurface();
/**
* Clears the {@link Surface} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param surface The surface to clear.
*/
void clearVideoSurface(@Nullable Surface surface);
/**
* Sets the {@link Surface} onto which video will be rendered. The caller is responsible for
* tracking the lifecycle of the surface, and must clear the surface by calling {@code
* setVideoSurface(null)} if the surface is destroyed.
*
* <p>If the surface is held by a {@link SurfaceView}, {@link TextureView} or {@link
* SurfaceHolder} then it's recommended to use {@link #setVideoSurfaceView(SurfaceView)}, {@link
* #setVideoTextureView(TextureView)} or {@link #setVideoSurfaceHolder(SurfaceHolder)} rather
* than this method, since passing the holder allows the player to track the lifecycle of the
* surface automatically.
*
* @param surface The {@link Surface}.
*/
void setVideoSurface(@Nullable Surface surface);
/**
* Sets the {@link SurfaceHolder} that holds the {@link Surface} onto which video will be
* rendered. The player will track the lifecycle of the surface automatically.
*
* @param surfaceHolder The surface holder.
*/
void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder);
/**
* Clears the {@link SurfaceHolder} that holds the {@link Surface} onto which video is being
* rendered if it matches the one passed. Else does nothing.
*
* @param surfaceHolder The surface holder to clear.
*/
void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder);
/**
* Sets the {@link SurfaceView} onto which video will be rendered. The player will track the
* lifecycle of the surface automatically.
*
* @param surfaceView The surface view.
*/
void setVideoSurfaceView(@Nullable SurfaceView surfaceView);
/**
* Clears the {@link SurfaceView} onto which video is being rendered if it matches the one
* passed. Else does nothing.
*
* @param surfaceView The texture view to clear.
*/
void clearVideoSurfaceView(@Nullable SurfaceView surfaceView);
/**
* Sets the {@link TextureView} onto which video will be rendered. The player will track the
* lifecycle of the surface automatically.
*
* @param textureView The texture view.
*/
void setVideoTextureView(@Nullable TextureView textureView);
/**
* Clears the {@link TextureView} onto which video is being rendered if it matches the one
* passed. Else does nothing.
*
* @param textureView The texture view to clear.
*/
void clearVideoTextureView(@Nullable TextureView textureView);
}
/**
* Listener of changes in player state.
*
@ -1152,10 +1012,6 @@ public interface Player {
/** Command to get the text that should currently be displayed by the player. */
int COMMAND_GET_TEXT = 22;
/** Returns the component of this player for video output, or null if video is not supported. */
@Nullable
VideoComponent getVideoComponent();
/**
* Returns the {@link Looper} associated with the application thread that's used to access the
* player and on which player events are received.
@ -1830,6 +1686,117 @@ public interface Player {
*/
float getVolume();
/**
* Sets a listener to receive video frame metadata events.
*
* <p>This method is intended to be called by the same component that sets the {@link Surface}
* onto which video will be rendered. If using ExoPlayer's standard UI components, this method
* should not be called directly from application code.
*
* @param listener The listener.
*/
void setVideoFrameMetadataListener(VideoFrameMetadataListener listener);
/**
* Clears the listener which receives video frame metadata events if it matches the one passed.
* Else does nothing.
*
* @param listener The listener to clear.
*/
void clearVideoFrameMetadataListener(VideoFrameMetadataListener listener);
/**
* Sets a listener of camera motion events.
*
* @param listener The listener.
*/
void setCameraMotionListener(CameraMotionListener listener);
/**
* Clears the listener which receives camera motion events if it matches the one passed. Else does
* nothing.
*
* @param listener The listener to clear.
*/
void clearCameraMotionListener(CameraMotionListener listener);
/**
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
* currently set on the player.
*/
void clearVideoSurface();
/**
* Clears the {@link Surface} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param surface The surface to clear.
*/
void clearVideoSurface(@Nullable Surface surface);
/**
* Sets the {@link Surface} onto which video will be rendered. The caller is responsible for
* tracking the lifecycle of the surface, and must clear the surface by calling {@code
* setVideoSurface(null)} if the surface is destroyed.
*
* <p>If the surface is held by a {@link SurfaceView}, {@link TextureView} or {@link
* SurfaceHolder} then it's recommended to use {@link #setVideoSurfaceView(SurfaceView)}, {@link
* #setVideoTextureView(TextureView)} or {@link #setVideoSurfaceHolder(SurfaceHolder)} rather than
* this method, since passing the holder allows the player to track the lifecycle of the surface
* automatically.
*
* @param surface The {@link Surface}.
*/
void setVideoSurface(@Nullable Surface surface);
/**
* Sets the {@link SurfaceHolder} that holds the {@link Surface} onto which video will be
* rendered. The player will track the lifecycle of the surface automatically.
*
* @param surfaceHolder The surface holder.
*/
void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder);
/**
* Clears the {@link SurfaceHolder} that holds the {@link Surface} onto which video is being
* rendered if it matches the one passed. Else does nothing.
*
* @param surfaceHolder The surface holder to clear.
*/
void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder);
/**
* Sets the {@link SurfaceView} onto which video will be rendered. The player will track the
* lifecycle of the surface automatically.
*
* @param surfaceView The surface view.
*/
void setVideoSurfaceView(@Nullable SurfaceView surfaceView);
/**
* Clears the {@link SurfaceView} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param surfaceView The texture view to clear.
*/
void clearVideoSurfaceView(@Nullable SurfaceView surfaceView);
/**
* Sets the {@link TextureView} onto which video will be rendered. The player will track the
* lifecycle of the surface automatically.
*
* @param textureView The texture view.
*/
void setVideoTextureView(@Nullable TextureView textureView);
/**
* Clears the {@link TextureView} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param textureView The texture view to clear.
*/
void clearVideoTextureView(@Nullable TextureView textureView);
/** Returns the current {@link Cue Cues}. This list may be empty. */
List<Cue> getCurrentCues();

View File

@ -18,6 +18,10 @@ package com.google.android.exoplayer2;
import android.content.Context;
import android.media.AudioTrack;
import android.os.Looper;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.analytics.AnalyticsCollector;
@ -48,6 +52,9 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.VideoListener;
import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
import java.util.List;
/**
@ -223,6 +230,146 @@ public interface ExoPlayer extends Player {
boolean getSkipSilenceEnabled();
}
/** The video component of an {@link ExoPlayer}. */
interface VideoComponent {
/**
* Sets the {@link C.VideoScalingMode}.
*
* @param videoScalingMode The {@link C.VideoScalingMode}.
*/
void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode);
/** Returns the {@link C.VideoScalingMode}. */
@C.VideoScalingMode
int getVideoScalingMode();
/**
* Adds a listener to receive video events.
*
* @param listener The listener to register.
*/
void addVideoListener(VideoListener listener);
/**
* Removes a listener of video events.
*
* @param listener The listener to unregister.
*/
void removeVideoListener(VideoListener listener);
/**
* Sets a listener to receive video frame metadata events.
*
* <p>This method is intended to be called by the same component that sets the {@link Surface}
* onto which video will be rendered. If using ExoPlayer's standard UI components, this method
* should not be called directly from application code.
*
* @param listener The listener.
*/
void setVideoFrameMetadataListener(VideoFrameMetadataListener listener);
/**
* Clears the listener which receives video frame metadata events if it matches the one passed.
* Else does nothing.
*
* @param listener The listener to clear.
*/
void clearVideoFrameMetadataListener(VideoFrameMetadataListener listener);
/**
* Sets a listener of camera motion events.
*
* @param listener The listener.
*/
void setCameraMotionListener(CameraMotionListener listener);
/**
* Clears the listener which receives camera motion events if it matches the one passed. Else
* does nothing.
*
* @param listener The listener to clear.
*/
void clearCameraMotionListener(CameraMotionListener listener);
/**
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
* currently set on the player.
*/
void clearVideoSurface();
/**
* Clears the {@link Surface} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param surface The surface to clear.
*/
void clearVideoSurface(@Nullable Surface surface);
/**
* Sets the {@link Surface} onto which video will be rendered. The caller is responsible for
* tracking the lifecycle of the surface, and must clear the surface by calling {@code
* setVideoSurface(null)} if the surface is destroyed.
*
* <p>If the surface is held by a {@link SurfaceView}, {@link TextureView} or {@link
* SurfaceHolder} then it's recommended to use {@link #setVideoSurfaceView(SurfaceView)}, {@link
* #setVideoTextureView(TextureView)} or {@link #setVideoSurfaceHolder(SurfaceHolder)} rather
* than this method, since passing the holder allows the player to track the lifecycle of the
* surface automatically.
*
* @param surface The {@link Surface}.
*/
void setVideoSurface(@Nullable Surface surface);
/**
* Sets the {@link SurfaceHolder} that holds the {@link Surface} onto which video will be
* rendered. The player will track the lifecycle of the surface automatically.
*
* @param surfaceHolder The surface holder.
*/
void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder);
/**
* Clears the {@link SurfaceHolder} that holds the {@link Surface} onto which video is being
* rendered if it matches the one passed. Else does nothing.
*
* @param surfaceHolder The surface holder to clear.
*/
void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder);
/**
* Sets the {@link SurfaceView} onto which video will be rendered. The player will track the
* lifecycle of the surface automatically.
*
* @param surfaceView The surface view.
*/
void setVideoSurfaceView(@Nullable SurfaceView surfaceView);
/**
* Clears the {@link SurfaceView} onto which video is being rendered if it matches the one
* passed. Else does nothing.
*
* @param surfaceView The texture view to clear.
*/
void clearVideoSurfaceView(@Nullable SurfaceView surfaceView);
/**
* Sets the {@link TextureView} onto which video will be rendered. The player will track the
* lifecycle of the surface automatically.
*
* @param textureView The texture view.
*/
void setVideoTextureView(@Nullable TextureView textureView);
/**
* Clears the {@link TextureView} onto which video is being rendered if it matches the one
* passed. Else does nothing.
*
* @param textureView The texture view to clear.
*/
void clearVideoTextureView(@Nullable TextureView textureView);
}
/** The text component of an {@link ExoPlayer}. */
interface TextComponent {
@ -651,6 +798,10 @@ public interface ExoPlayer extends Player {
@Nullable
AudioComponent getAudioComponent();
/** Returns the component of this player for video output, or null if video is not supported. */
@Nullable
VideoComponent getVideoComponent();
/** Returns the component of this player for text output, or null if text is not supported. */
@Nullable
TextComponent getTextComponent();

View File

@ -25,6 +25,10 @@ import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.util.Pair;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.analytics.AnalyticsCollector;
@ -48,6 +52,8 @@ import com.google.android.exoplayer2.util.HandlerWrapper;
import com.google.android.exoplayer2.util.ListenerSet;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collections;
@ -1004,6 +1010,58 @@ import java.util.concurrent.CopyOnWriteArraySet;
return 1;
}
/** This method is not supported and does nothing. */
@Override
public void setVideoFrameMetadataListener(VideoFrameMetadataListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoFrameMetadataListener(VideoFrameMetadataListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void setCameraMotionListener(CameraMotionListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void clearCameraMotionListener(CameraMotionListener listener) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurface() {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurface(@Nullable Surface surface) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoSurface(@Nullable Surface surface) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoSurfaceView(@Nullable SurfaceView surfaceView) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) {}
/** This method is not supported and does nothing. */
@Override
public void setVideoTextureView(@Nullable TextureView textureView) {}
/** This method is not supported and does nothing. */
@Override
public void clearVideoTextureView(@Nullable TextureView textureView) {}
/** This method is not supported and returns an empty list. */
@Override
public ImmutableList<Cue> getCurrentCues() {

View File

@ -79,7 +79,7 @@ import java.util.concurrent.TimeoutException;
public class SimpleExoPlayer extends BasePlayer
implements ExoPlayer,
ExoPlayer.AudioComponent,
Player.VideoComponent,
ExoPlayer.VideoComponent,
ExoPlayer.TextComponent,
ExoPlayer.MetadataComponent,
ExoPlayer.DeviceComponent {

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.ui;
import static com.google.android.exoplayer2.Player.COMMAND_GET_TEXT;
import static com.google.android.exoplayer2.Player.COMMAND_SET_VIDEO_SURFACE;
import android.annotation.SuppressLint;
import android.content.Context;
@ -563,14 +564,13 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
@Nullable Player oldPlayer = this.player;
if (oldPlayer != null) {
oldPlayer.removeListener(componentListener);
@Nullable Player.VideoComponent oldVideoComponent = oldPlayer.getVideoComponent();
if (oldVideoComponent != null) {
if (oldPlayer.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)) {
if (surfaceView instanceof TextureView) {
oldVideoComponent.clearVideoTextureView((TextureView) surfaceView);
oldPlayer.clearVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SphericalGLSurfaceView) {
((SphericalGLSurfaceView) surfaceView).setVideoComponent(null);
((SphericalGLSurfaceView) surfaceView).setPlayer(null);
} else if (surfaceView instanceof SurfaceView) {
oldVideoComponent.clearVideoSurfaceView((SurfaceView) surfaceView);
oldPlayer.clearVideoSurfaceView((SurfaceView) surfaceView);
}
}
}
@ -585,16 +585,14 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
updateErrorMessage();
updateForCurrentTrackSelections(/* isNewPlayer= */ true);
if (player != null) {
@Nullable Player.VideoComponent newVideoComponent = player.getVideoComponent();
if (newVideoComponent != null) {
if (player.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)) {
if (surfaceView instanceof TextureView) {
newVideoComponent.setVideoTextureView((TextureView) surfaceView);
player.setVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SphericalGLSurfaceView) {
((SphericalGLSurfaceView) surfaceView).setVideoComponent(newVideoComponent);
((SphericalGLSurfaceView) surfaceView).setPlayer(player);
} else if (surfaceView instanceof SurfaceView) {
newVideoComponent.setVideoSurfaceView((SurfaceView) surfaceView);
player.setVideoSurfaceView((SurfaceView) surfaceView);
}
newVideoComponent.addVideoListener(componentListener);
}
if (subtitleView != null && player.isCommandAvailable(COMMAND_GET_TEXT)) {
subtitleView.setCues(player.getCurrentCues());

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.ui;
import static com.google.android.exoplayer2.Player.COMMAND_GET_TEXT;
import static com.google.android.exoplayer2.Player.COMMAND_SET_VIDEO_SURFACE;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.annotation.SuppressLint;
@ -572,15 +573,12 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
@Nullable Player oldPlayer = this.player;
if (oldPlayer != null) {
oldPlayer.removeListener(componentListener);
@Nullable Player.VideoComponent oldVideoComponent = oldPlayer.getVideoComponent();
if (oldVideoComponent != null) {
if (surfaceView instanceof TextureView) {
oldVideoComponent.clearVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SphericalGLSurfaceView) {
((SphericalGLSurfaceView) surfaceView).setVideoComponent(null);
} else if (surfaceView instanceof SurfaceView) {
oldVideoComponent.clearVideoSurfaceView((SurfaceView) surfaceView);
}
if (surfaceView instanceof TextureView) {
oldPlayer.clearVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SphericalGLSurfaceView) {
((SphericalGLSurfaceView) surfaceView).setPlayer(null);
} else if (surfaceView instanceof SurfaceView) {
oldPlayer.clearVideoSurfaceView((SurfaceView) surfaceView);
}
}
if (subtitleView != null) {
@ -594,16 +592,14 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
updateErrorMessage();
updateForCurrentTrackSelections(/* isNewPlayer= */ true);
if (player != null) {
@Nullable Player.VideoComponent newVideoComponent = player.getVideoComponent();
if (newVideoComponent != null) {
if (player.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)) {
if (surfaceView instanceof TextureView) {
newVideoComponent.setVideoTextureView((TextureView) surfaceView);
player.setVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SphericalGLSurfaceView) {
((SphericalGLSurfaceView) surfaceView).setVideoComponent(newVideoComponent);
((SphericalGLSurfaceView) surfaceView).setPlayer(player);
} else if (surfaceView instanceof SurfaceView) {
newVideoComponent.setVideoSurfaceView((SurfaceView) surfaceView);
player.setVideoSurfaceView((SurfaceView) surfaceView);
}
newVideoComponent.addVideoListener(componentListener);
}
if (subtitleView != null && player.isCommandAvailable(COMMAND_GET_TEXT)) {
subtitleView.setCues(player.getCurrentCues());

View File

@ -72,7 +72,7 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
private final SceneRenderer scene;
@Nullable private SurfaceTexture surfaceTexture;
@Nullable private Surface surface;
@Nullable private Player.VideoComponent videoComponent;
@Nullable private Player player;
private boolean useSensorRotation;
private boolean isStarted;
private boolean isOrientationListenerRegistered;
@ -125,23 +125,23 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
scene.setDefaultStereoMode(stereoMode);
}
/** Sets the {@link Player.VideoComponent} to use. */
public void setVideoComponent(@Nullable Player.VideoComponent newVideoComponent) {
if (newVideoComponent == videoComponent) {
/** Sets the {@link Player} to use. */
public void setPlayer(@Nullable Player newPlayer) {
if (newPlayer == player) {
return;
}
if (videoComponent != null) {
if (player != null) {
if (surface != null) {
videoComponent.clearVideoSurface(surface);
player.clearVideoSurface(surface);
}
videoComponent.clearVideoFrameMetadataListener(scene);
videoComponent.clearCameraMotionListener(scene);
player.clearVideoFrameMetadataListener(scene);
player.clearCameraMotionListener(scene);
}
videoComponent = newVideoComponent;
if (videoComponent != null) {
videoComponent.setVideoFrameMetadataListener(scene);
videoComponent.setCameraMotionListener(scene);
videoComponent.setVideoSurface(surface);
player = newPlayer;
if (this.player != null) {
player.setVideoFrameMetadataListener(scene);
player.setCameraMotionListener(scene);
player.setVideoSurface(surface);
}
}
@ -174,8 +174,8 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
mainHandler.post(
() -> {
if (surface != null) {
if (videoComponent != null) {
videoComponent.clearVideoSurface(surface);
if (player != null) {
player.clearVideoSurface(surface);
}
releaseSurface(surfaceTexture, surface);
surfaceTexture = null;
@ -206,8 +206,8 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
Surface oldSurface = this.surface;
this.surfaceTexture = surfaceTexture;
this.surface = new Surface(surfaceTexture);
if (videoComponent != null) {
videoComponent.setVideoSurface(surface);
if (player != null) {
player.setVideoSurface(surface);
}
releaseSurface(oldSurfaceTexture, oldSurface);
});

View File

@ -16,6 +16,10 @@
package com.google.android.exoplayer2.testutil;
import android.os.Looper;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.BasePlayer;
import com.google.android.exoplayer2.ExoPlaybackException;
@ -37,6 +41,8 @@ import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
import java.util.List;
/**
@ -440,6 +446,71 @@ public class StubExoPlayer extends BasePlayer implements ExoPlayer {
throw new UnsupportedOperationException();
}
@Override
public void setVideoFrameMetadataListener(VideoFrameMetadataListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void clearVideoFrameMetadataListener(VideoFrameMetadataListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void setCameraMotionListener(CameraMotionListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void clearCameraMotionListener(CameraMotionListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void clearVideoSurface() {
throw new UnsupportedOperationException();
}
@Override
public void clearVideoSurface(@Nullable Surface surface) {
throw new UnsupportedOperationException();
}
@Override
public void setVideoSurface(@Nullable Surface surface) {
throw new UnsupportedOperationException();
}
@Override
public void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {
throw new UnsupportedOperationException();
}
@Override
public void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {
throw new UnsupportedOperationException();
}
@Override
public void setVideoSurfaceView(@Nullable SurfaceView surfaceView) {
throw new UnsupportedOperationException();
}
@Override
public void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) {
throw new UnsupportedOperationException();
}
@Override
public void setVideoTextureView(@Nullable TextureView textureView) {
throw new UnsupportedOperationException();
}
@Override
public void clearVideoTextureView(@Nullable TextureView textureView) {
throw new UnsupportedOperationException();
}
@Override
public List<Cue> getCurrentCues() {
throw new UnsupportedOperationException();