提交 c577d9d3 编写于 作者: O olly 提交者: Oliver Woodman

Let SimpleExoPlayerView/LeanbackPlayerAdapter bind with any Player

Also sanitize naming (PlayerView/PlayerControlView).

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=182364487
上级 605aeb3a
......@@ -6,6 +6,10 @@
`SimpleExoPlayerView` is configured to use `TextureView`
([#91](https://github.com/google/ExoPlayer/issues/91)).
* Player interface:
* Add `Player.VideoComponent`, `Player.TextComponent` and
`Player.MetadataComponent` interfaces that define optional video, text and
metadata output functionality. New `getVideoComponent`, `getTextComponent`
and `getMetadataComponent` methods provide access to this functionality.
* Add optional parameter to `stop` to reset the player when stopping.
* Add a reason to `EventListener.onTimelineChanged` to distinguish between
initial preparation, reset and dynamic updates.
......@@ -17,6 +21,10 @@
more customization of the message. Now supports setting a message delivery
playback position and/or a delivery handler.
([#2189](https://github.com/google/ExoPlayer/issues/2189)).
* UI components:
* Generalized player and control views to allow them to bind with any
`Player`, and renamed them to `PlayerView` and `PlayerControlView`
respectively.
* Buffering:
* Allow a back-buffer of media to be retained behind the current playback
position, for fast backward seeking. The back-buffer can be configured by
......
......@@ -39,8 +39,8 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.castdemo.DemoUtil.Sample;
import com.google.android.exoplayer2.ext.cast.CastPlayer;
import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.gms.cast.framework.CastButtonFactory;
import com.google.android.gms.cast.framework.CastContext;
......@@ -50,8 +50,8 @@ import com.google.android.gms.cast.framework.CastContext;
public class MainActivity extends AppCompatActivity implements OnClickListener,
PlayerManager.QueuePositionListener {
private SimpleExoPlayerView simpleExoPlayerView;
private PlaybackControlView castControlView;
private PlayerView localPlayerView;
private PlayerControlView castControlView;
private PlayerManager playerManager;
private MediaQueueAdapter listAdapter;
private CastContext castContext;
......@@ -66,8 +66,8 @@ public class MainActivity extends AppCompatActivity implements OnClickListener,
setContentView(R.layout.main_activity);
simpleExoPlayerView = findViewById(R.id.player_view);
simpleExoPlayerView.requestFocus();
localPlayerView = findViewById(R.id.local_player_view);
localPlayerView.requestFocus();
castControlView = findViewById(R.id.cast_control_view);
......@@ -93,8 +93,13 @@ public class MainActivity extends AppCompatActivity implements OnClickListener,
@Override
public void onResume() {
super.onResume();
playerManager = PlayerManager.createPlayerManager(this, simpleExoPlayerView, castControlView,
this, castContext);
playerManager =
PlayerManager.createPlayerManager(
/* queuePositionListener= */ this,
localPlayerView,
castControlView,
/* context= */ this,
castContext);
}
@Override
......
......@@ -40,8 +40,8 @@ import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.gms.cast.MediaInfo;
......@@ -73,12 +73,12 @@ import java.util.ArrayList;
private static final DefaultHttpDataSourceFactory DATA_SOURCE_FACTORY =
new DefaultHttpDataSourceFactory(USER_AGENT, BANDWIDTH_METER);
private final SimpleExoPlayerView exoPlayerView;
private final PlaybackControlView castControlView;
private final PlayerView localPlayerView;
private final PlayerControlView castControlView;
private final SimpleExoPlayer exoPlayer;
private final CastPlayer castPlayer;
private final ArrayList<DemoUtil.Sample> mediaQueue;
private final QueuePositionListener listener;
private final QueuePositionListener queuePositionListener;
private DynamicConcatenatingMediaSource dynamicConcatenatingMediaSource;
private boolean castMediaQueueCreationPending;
......@@ -86,25 +86,33 @@ import java.util.ArrayList;
private Player currentPlayer;
/**
* @param listener A {@link QueuePositionListener} for queue position changes.
* @param exoPlayerView The {@link SimpleExoPlayerView} for local playback.
* @param castControlView The {@link PlaybackControlView} to control remote playback.
* @param queuePositionListener A {@link QueuePositionListener} for queue position changes.
* @param localPlayerView The {@link PlayerView} for local playback.
* @param castControlView The {@link PlayerControlView} to control remote playback.
* @param context A {@link Context}.
* @param castContext The {@link CastContext}.
*/
public static PlayerManager createPlayerManager(QueuePositionListener listener,
SimpleExoPlayerView exoPlayerView, PlaybackControlView castControlView, Context context,
public static PlayerManager createPlayerManager(
QueuePositionListener queuePositionListener,
PlayerView localPlayerView,
PlayerControlView castControlView,
Context context,
CastContext castContext) {
PlayerManager playerManager = new PlayerManager(listener, exoPlayerView, castControlView,
context, castContext);
PlayerManager playerManager =
new PlayerManager(
queuePositionListener, localPlayerView, castControlView, context, castContext);
playerManager.init();
return playerManager;
}
private PlayerManager(QueuePositionListener listener, SimpleExoPlayerView exoPlayerView,
PlaybackControlView castControlView, Context context, CastContext castContext) {
this.listener = listener;
this.exoPlayerView = exoPlayerView;
private PlayerManager(
QueuePositionListener queuePositionListener,
PlayerView localPlayerView,
PlayerControlView castControlView,
Context context,
CastContext castContext) {
this.queuePositionListener = queuePositionListener;
this.localPlayerView = localPlayerView;
this.castControlView = castControlView;
mediaQueue = new ArrayList<>();
currentItemIndex = C.INDEX_UNSET;
......@@ -113,7 +121,7 @@ import java.util.ArrayList;
RenderersFactory renderersFactory = new DefaultRenderersFactory(context, null);
exoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);
exoPlayer.addListener(this);
exoPlayerView.setPlayer(exoPlayer);
localPlayerView.setPlayer(exoPlayer);
castPlayer = new CastPlayer(castContext);
castPlayer.addListener(this);
......@@ -242,7 +250,7 @@ import java.util.ArrayList;
*/
public boolean dispatchKeyEvent(KeyEvent event) {
if (currentPlayer == exoPlayer) {
return exoPlayerView.dispatchKeyEvent(event);
return localPlayerView.dispatchKeyEvent(event);
} else /* currentPlayer == castPlayer */ {
return castControlView.dispatchKeyEvent(event);
}
......@@ -256,7 +264,7 @@ import java.util.ArrayList;
mediaQueue.clear();
castPlayer.setSessionAvailabilityListener(null);
castPlayer.release();
exoPlayerView.setPlayer(null);
localPlayerView.setPlayer(null);
exoPlayer.release();
}
......@@ -309,10 +317,10 @@ import java.util.ArrayList;
// View management.
if (currentPlayer == exoPlayer) {
exoPlayerView.setVisibility(View.VISIBLE);
localPlayerView.setVisibility(View.VISIBLE);
castControlView.hide();
} else /* currentPlayer == castPlayer */ {
exoPlayerView.setVisibility(View.GONE);
localPlayerView.setVisibility(View.GONE);
castControlView.show();
}
......@@ -380,7 +388,7 @@ import java.util.ArrayList;
if (this.currentItemIndex != currentItemIndex) {
int oldIndex = this.currentItemIndex;
this.currentItemIndex = currentItemIndex;
listener.onQueuePositionChanged(oldIndex, currentItemIndex);
queuePositionListener.onQueuePositionChanged(oldIndex, currentItemIndex);
}
}
......
......@@ -19,7 +19,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
<com.google.android.exoplayer2.ui.SimpleExoPlayerView android:id="@+id/player_view"
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/local_player_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="12"
......@@ -42,7 +42,7 @@
android:layout_alignParentBottom="true"
android:padding="30dp"/>
</RelativeLayout>
<com.google.android.exoplayer2.ui.PlaybackControlView android:id="@+id/cast_control_view"
<com.google.android.exoplayer2.ui.PlayerControlView android:id="@+id/cast_control_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
......
......@@ -18,7 +18,7 @@ package com.google.android.exoplayer2.imademo;
import android.app.Activity;
import android.os.Bundle;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.ui.PlayerView;
/**
* Main Activity for the IMA plugin demo. {@link ExoPlayer} objects are created by
......@@ -26,7 +26,7 @@ import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
*/
public final class MainActivity extends Activity {
private SimpleExoPlayerView playerView;
private PlayerView playerView;
private PlayerManager player;
@Override
......
......@@ -38,7 +38,7 @@ import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
......@@ -68,7 +68,7 @@ import com.google.android.exoplayer2.util.Util;
new DefaultBandwidthMeter());
}
public void init(Context context, SimpleExoPlayerView simpleExoPlayerView) {
public void init(Context context, PlayerView playerView) {
// Create a default track selector.
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
......@@ -79,7 +79,7 @@ import com.google.android.exoplayer2.util.Util;
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
playerView.setPlayer(player);
// This is the MediaSource representing the content media (i.e. not the ad).
String contentUrl = context.getString(R.string.content_url);
......@@ -92,7 +92,7 @@ import com.google.android.exoplayer2.util.Util;
contentMediaSource,
/* adMediaSourceFactory= */ this,
adsLoader,
simpleExoPlayerView.getOverlayFrameLayout(),
playerView.getOverlayFrameLayout(),
/* eventHandler= */ null,
/* eventListener= */ null);
......
......@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.exoplayer2.ui.SimpleExoPlayerView
<com.google.android.exoplayer2.ui.PlayerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/player_view"
android:layout_width="match_parent"
......
......@@ -68,8 +68,8 @@ import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedT
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.DebugTextViewHelper;
import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.HttpDataSource;
......@@ -79,11 +79,9 @@ import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.UUID;
/**
* An activity that plays media using {@link SimpleExoPlayer}.
*/
public class PlayerActivity extends Activity implements OnClickListener,
PlaybackControlView.VisibilityListener {
/** An activity that plays media using {@link SimpleExoPlayer}. */
public class PlayerActivity extends Activity
implements OnClickListener, PlayerControlView.VisibilityListener {
public static final String DRM_SCHEME_EXTRA = "drm_scheme";
public static final String DRM_LICENSE_URL = "drm_license_url";
......@@ -112,7 +110,7 @@ public class PlayerActivity extends Activity implements OnClickListener,
private Handler mainHandler;
private EventLogger eventLogger;
private SimpleExoPlayerView simpleExoPlayerView;
private PlayerView playerView;
private LinearLayout debugRootView;
private TextView debugTextView;
private Button retryButton;
......@@ -156,9 +154,9 @@ public class PlayerActivity extends Activity implements OnClickListener,
retryButton = findViewById(R.id.retry_button);
retryButton.setOnClickListener(this);
simpleExoPlayerView = findViewById(R.id.player_view);
simpleExoPlayerView.setControllerVisibilityListener(this);
simpleExoPlayerView.requestFocus();
playerView = findViewById(R.id.player_view);
playerView.setControllerVisibilityListener(this);
playerView.requestFocus();
}
@Override
......@@ -223,7 +221,7 @@ public class PlayerActivity extends Activity implements OnClickListener,
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// See whether the player view wants to handle media or DPAD keys events.
return simpleExoPlayerView.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
return playerView.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
// OnClickListener methods
......@@ -303,7 +301,7 @@ public class PlayerActivity extends Activity implements OnClickListener,
player.addAudioDebugListener(eventLogger);
player.addVideoDebugListener(eventLogger);
simpleExoPlayerView.setPlayer(player);
playerView.setPlayer(player);
player.setPlayWhenReady(shouldAutoPlay);
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
debugViewHelper.start();
......@@ -470,7 +468,7 @@ public class PlayerActivity extends Activity implements OnClickListener,
.newInstance(this, adTagUri);
adUiViewGroup = new FrameLayout(this);
// The demo app has a non-null overlay frame layout.
simpleExoPlayerView.getOverlayFrameLayout().addView(adUiViewGroup);
playerView.getOverlayFrameLayout().addView(adUiViewGroup);
}
AdsMediaSource.MediaSourceFactory adMediaSourceFactory =
new AdsMediaSource.MediaSourceFactory() {
......@@ -495,7 +493,7 @@ public class PlayerActivity extends Activity implements OnClickListener,
adsLoader.release();
adsLoader = null;
loadedAdTagUri = null;
simpleExoPlayerView.getOverlayFrameLayout().removeAllViews();
playerView.getOverlayFrameLayout().removeAllViews();
}
}
......
......@@ -20,7 +20,7 @@
android:layout_height="match_parent"
android:keepScreenOn="true">
<com.google.android.exoplayer2.ui.SimpleExoPlayerView android:id="@+id/player_view"
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
......
......@@ -27,7 +27,4 @@ locally. Instructions for doing this can be found in ExoPlayer's
## Using the extension ##
Create a `CastPlayer` and use it to integrate Cast into your app using
ExoPlayer's common Player interface. You can try the Cast Extension to see how a
[PlaybackControlView][] can be used to control playback in a remote receiver app.
[PlaybackControlView]: https://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer2/ui/PlaybackControlView.html
ExoPlayer's common `Player` interface.
......@@ -280,6 +280,16 @@ public final class CastPlayer implements Player {
// Player implementation.
@Override
public VideoComponent getVideoComponent() {
return null;
}
@Override
public TextComponent getTextComponent() {
return null;
}
@Override
public void addListener(EventListener listener) {
listeners.add(listener);
......
......@@ -33,13 +33,11 @@ import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Player.TimelineChangeReason;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.util.ErrorMessageProvider;
import com.google.android.exoplayer2.video.VideoListener;
/**
* Leanback {@code PlayerAdapter} implementation for {@link SimpleExoPlayer}.
*/
/** Leanback {@code PlayerAdapter} implementation for {@link Player}. */
public final class LeanbackPlayerAdapter extends PlayerAdapter {
static {
......@@ -47,7 +45,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
}
private final Context context;
private final SimpleExoPlayer player;
private final Player player;
private final Handler handler;
private final ComponentListener componentListener;
private final Runnable updateProgressRunnable;
......@@ -60,14 +58,14 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
/**
* Builds an instance. Note that the {@code PlayerAdapter} does not manage the lifecycle of the
* {@link SimpleExoPlayer} instance. The caller remains responsible for releasing the player when
* it's no longer required.
* {@link Player} instance. The caller remains responsible for releasing the player when it's no
* longer required.
*
* @param context The current context (activity).
* @param player Instance of your exoplayer that needs to be configured.
* @param updatePeriodMs The delay between player control updates, in milliseconds.
*/
public LeanbackPlayerAdapter(Context context, SimpleExoPlayer player, final int updatePeriodMs) {
public LeanbackPlayerAdapter(Context context, Player player, final int updatePeriodMs) {
this.context = context;
this.player = player;
handler = new Handler();
......@@ -115,13 +113,19 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
}
notifyStateChanged();
player.addListener(componentListener);
player.addVideoListener(componentListener);
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.addVideoListener(componentListener);
}
}
@Override
public void onDetachedFromHost() {
player.removeListener(componentListener);
player.removeVideoListener(componentListener);
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.removeVideoListener(componentListener);
}
if (surfaceHolderGlueHost != null) {
surfaceHolderGlueHost.setSurfaceHolderCallback(null);
surfaceHolderGlueHost = null;
......@@ -196,7 +200,10 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
/* package */ void setVideoSurface(Surface surface) {
hasSurface = surface != null;
player.setVideoSurface(surface);
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.setVideoSurface(surface);
}
maybeNotifyPreparedStateChanged(getCallback());
}
......@@ -219,8 +226,8 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
}
}
private final class ComponentListener extends Player.DefaultEventListener implements
SimpleExoPlayer.VideoListener, SurfaceHolder.Callback {
private final class ComponentListener extends Player.DefaultEventListener
implements SurfaceHolder.Callback, VideoListener {
// SurfaceHolder.Callback implementation.
......@@ -274,11 +281,11 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
callback.onBufferedPositionChanged(LeanbackPlayerAdapter.this);
}
// SimpleExoplayerView.Callback implementation.
// VideoListener implementation.
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
float pixelWidthHeightRatio) {
public void onVideoSizeChanged(
int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
getCallback().onVideoSizeChanged(LeanbackPlayerAdapter.this, width, height);
}
......
......@@ -124,6 +124,16 @@ import java.util.concurrent.CopyOnWriteArraySet;
internalPlayerHandler = new Handler(internalPlayer.getPlaybackLooper());
}
@Override
public VideoComponent getVideoComponent() {
return null;
}
@Override
public TextComponent getTextComponent() {
return null;
}
@Override
public Looper getPlaybackLooper() {
return internalPlayer.getPlaybackLooper();
......
......@@ -18,8 +18,14 @@ package com.google.android.exoplayer2;
import android.os.Looper;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.video.VideoListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......@@ -44,6 +50,130 @@ import java.lang.annotation.RetentionPolicy;
*/
public interface Player {
/** The video component of a {@link Player}. */
interface VideoComponent {
/**
* Sets the video scaling mode.
*
* @param videoScalingMode The video scaling mode.
*/
void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode);
/** Returns the video scaling mode. */
@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);
/**
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
* currently set on the player.
*/
void clearVideoSurface();
/**
* 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(Surface surface);
/**
* 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(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(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(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(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(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(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(TextureView textureView);
}
/** The text component of a {@link Player}. */
interface TextComponent {
/**
* Registers an output to receive text events.
*
* @param listener The output to register.
*/
void addTextOutput(TextOutput listener);
/**
* Removes a text output.
*
* @param listener The output to remove.
*/
void removeTextOutput(TextOutput listener);
}
/**
* Listener of changes in player state.
*/
......@@ -298,6 +428,14 @@ public interface Player {
*/
int TIMELINE_CHANGE_REASON_DYNAMIC = 2;
/** 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();
/**
* Register a listener to receive events from the player. The listener's methods will be called on
* the thread that was used to construct the player. However, if the thread used to construct the
......
......@@ -50,39 +50,11 @@ import java.util.concurrent.CopyOnWriteArraySet;
* be obtained from {@link ExoPlayerFactory}.
*/
@TargetApi(16)
public class SimpleExoPlayer implements ExoPlayer {
public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player.TextComponent {
/**
* A listener for video rendering information from a {@link SimpleExoPlayer}.
*/
public interface VideoListener {
/**
* Called each time there's a change in the size of the video being rendered.
*
* @param width The video width in pixels.
* @param height The video height in pixels.
* @param unappliedRotationDegrees For videos that require a rotation, this is the clockwise
* rotation in degrees that the application should apply for the video for it to be rendered
* in the correct orientation. This value will always be zero on API levels 21 and above,
* since the renderer will apply all necessary rotations internally. On earlier API levels
* this is not possible. Applications that use {@link android.view.TextureView} can apply
* the rotation by calling {@link android.view.TextureView#setTransform}. Applications that
* do not expect to encounter rotated videos can safely ignore this parameter.
* @param pixelWidthHeightRatio The width to height ratio of each pixel. For the normal case
* of square pixels this will be equal to 1.0. Different values are indicative of anamorphic
* content.
*/
void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
float pixelWidthHeightRatio);
/**
* Called when a frame is rendered for the first time since setting the surface, and when a
* frame is rendered for the first time since a video track was selected.
*/
void onRenderedFirstFrame();
}
/** @deprecated Use {@link com.google.android.exoplayer2.video.VideoListener}. */
@Deprecated
public interface VideoListener extends com.google.android.exoplayer2.video.VideoListener {}
private static final String TAG = "SimpleExoPlayer";
......@@ -90,7 +62,8 @@ public class SimpleExoPlayer implements ExoPlayer {
private final ExoPlayer player;
private final ComponentListener componentListener;
private final CopyOnWriteArraySet<VideoListener> videoListeners;
private final CopyOnWriteArraySet<com.google.android.exoplayer2.video.VideoListener>
videoListeners;
private final CopyOnWriteArraySet<TextOutput> textOutputs;
private final CopyOnWriteArraySet<MetadataOutput> metadataOutputs;
private final CopyOnWriteArraySet<VideoRendererEventListener> videoDebugListeners;
......@@ -154,14 +127,25 @@ public class SimpleExoPlayer implements ExoPlayer {
player = createExoPlayerImpl(renderers, trackSelector, loadControl, clock);
}
@Override
public VideoComponent getVideoComponent() {
return this;
}
@Override
public TextComponent getTextComponent() {
return this;
}
/**
* Sets the video scaling mode.
* <p>
* Note that the scaling mode only applies if a {@link MediaCodec}-based video {@link Renderer} is
* enabled and if the output surface is owned by a {@link android.view.SurfaceView}.
*
* <p>Note that the scaling mode only applies if a {@link MediaCodec}-based video {@link Renderer}
* is enabled and if the output surface is owned by a {@link android.view.SurfaceView}.
*
* @param videoScalingMode The video scaling mode.
*/
@Override
public void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode) {
this.videoScalingMode = videoScalingMode;
for (Renderer renderer : renderers) {
......@@ -175,57 +159,30 @@ public class SimpleExoPlayer implements ExoPlayer {
}
}
/**
* Returns the video scaling mode.
*/
@Override
public @C.VideoScalingMode int getVideoScalingMode() {
return videoScalingMode;
}
/**
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
* currently set on the player.
*/
@Override
public void clearVideoSurface() {
setVideoSurface(null);
}
/**
* 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}.
*/
@Override
public void setVideoSurface(Surface surface) {
removeSurfaceCallbacks();
setVideoSurfaceInternal(surface, false);
}
/**
* 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.
*/
@Override
public void clearVideoSurface(Surface surface) {
if (surface != null && surface == this.surface) {
setVideoSurface(null);
}
}
/**
* 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.
*/
@Override
public void setVideoSurfaceHolder(SurfaceHolder surfaceHolder) {
removeSurfaceCallbacks();
this.surfaceHolder = surfaceHolder;
......@@ -238,44 +195,24 @@ public class SimpleExoPlayer implements ExoPlayer {
}
}
/**
* 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.
*/
@Override
public void clearVideoSurfaceHolder(SurfaceHolder surfaceHolder) {
if (surfaceHolder != null && surfaceHolder == this.surfaceHolder) {
setVideoSurfaceHolder(null);
}
}
/**
* 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.
*/
@Override
public void setVideoSurfaceView(SurfaceView surfaceView) {
setVideoSurfaceHolder(surfaceView == null ? null : surfaceView.getHolder());
}
/**
* 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.
*/
@Override
public void clearVideoSurfaceView(SurfaceView surfaceView) {
clearVideoSurfaceHolder(surfaceView == null ? null : surfaceView.getHolder());
}
/**
* 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.
*/
@Override
public void setVideoTextureView(TextureView textureView) {
removeSurfaceCallbacks();
this.textureView = textureView;
......@@ -292,12 +229,7 @@ public class SimpleExoPlayer implements ExoPlayer {
}
}
/**
* 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.
*/
@Override
public void clearVideoTextureView(TextureView textureView) {
if (textureView != null && textureView == this.textureView) {
setVideoTextureView(null);
......@@ -446,21 +378,13 @@ public class SimpleExoPlayer implements ExoPlayer {
return audioDecoderCounters;
}
/**
* Adds a listener to receive video events.
*
* @param listener The listener to register.
*/
public void addVideoListener(VideoListener listener) {
@Override
public void addVideoListener(com.google.android.exoplayer2.video.VideoListener listener) {
videoListeners.add(listener);
}
/**
* Removes a listener of video events.
*
* @param listener The listener to unregister.
*/
public void removeVideoListener(VideoListener listener) {
@Override
public void removeVideoListener(com.google.android.exoplayer2.video.VideoListener listener) {
videoListeners.remove(listener);
}
......@@ -468,7 +392,7 @@ public class SimpleExoPlayer implements ExoPlayer {
* Sets a listener to receive video events, removing all existing listeners.
*
* @param listener The listener.
* @deprecated Use {@link #addVideoListener(VideoListener)}.
* @deprecated Use {@link #addVideoListener(com.google.android.exoplayer2.video.VideoListener)}.
*/
@Deprecated
public void setVideoListener(VideoListener listener) {
......@@ -479,30 +403,23 @@ public class SimpleExoPlayer implements ExoPlayer {
}
/**
* Equivalent to {@link #removeVideoListener(VideoListener)}.
* Equivalent to {@link #removeVideoListener(com.google.android.exoplayer2.video.VideoListener)}.
*
* @param listener The listener to clear.
* @deprecated Use {@link #removeVideoListener(VideoListener)}.
* @deprecated Use {@link
* #removeVideoListener(com.google.android.exoplayer2.video.VideoListener)}.
*/
@Deprecated
public void clearVideoListener(VideoListener listener) {
removeVideoListener(listener);
}
/**
* Registers an output to receive text events.
*
* @param listener The output to register.
*/
@Override
public void addTextOutput(TextOutput listener) {
textOutputs.add(listener);
}
/**
* Removes a text output.
*
* @param listener The output to remove.
*/
@Override
public void removeTextOutput(TextOutput listener) {
textOutputs.remove(listener);
}
......@@ -532,20 +449,10 @@ public class SimpleExoPlayer implements ExoPlayer {
removeTextOutput(output);
}
/**
* Registers an output to receive metadata events.
*
* @param listener The output to register.
*/
public void addMetadataOutput(MetadataOutput listener) {
metadataOutputs.add(listener);
}
/**
* Removes a metadata output.
*
* @param listener The output to remove.
*/
public void removeMetadataOutput(MetadataOutput listener) {
metadataOutputs.remove(listener);
}
......@@ -978,7 +885,7 @@ public class SimpleExoPlayer implements ExoPlayer {
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
float pixelWidthHeightRatio) {
for (VideoListener videoListener : videoListeners) {
for (com.google.android.exoplayer2.video.VideoListener videoListener : videoListeners) {
videoListener.onVideoSizeChanged(width, height, unappliedRotationDegrees,
pixelWidthHeightRatio);
}
......@@ -991,7 +898,7 @@ public class SimpleExoPlayer implements ExoPlayer {
@Override
public void onRenderedFirstFrame(Surface surface) {
if (SimpleExoPlayer.this.surface == surface) {
for (VideoListener videoListener : videoListeners) {
for (com.google.android.exoplayer2.video.VideoListener videoListener : videoListeners) {
videoListener.onRenderedFirstFrame();
}
}
......
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.video;
/** A listener for metadata corresponding to video being rendered. */
public interface VideoListener {
/**
* Called each time there's a change in the size of the video being rendered.
*
* @param width The video width in pixels.
* @param height The video height in pixels.
* @param unappliedRotationDegrees For videos that require a rotation, this is the clockwise
* rotation in degrees that the application should apply for the video for it to be rendered
* in the correct orientation. This value will always be zero on API levels 21 and above,
* since the renderer will apply all necessary rotations internally. On earlier API levels
* this is not possible. Applications that use {@link android.view.TextureView} can apply the
* rotation by calling {@link android.view.TextureView#setTransform}. Applications that do not
* expect to encounter rotated videos can safely ignore this parameter.
* @param pixelWidthHeightRatio The width to height ratio of each pixel. For the normal case of
* square pixels this will be equal to 1.0. Different values are indicative of anamorphic
* content.
*/
void onVideoSizeChanged(
int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio);
/**
* Called when a frame is rendered for the first time since setting the surface, and when a frame
* is rendered for the first time since a video track was selected.
*/
void onRenderedFirstFrame();
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<merge>
<include layout="@layout/exo_playback_control_view"/>
</merge>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<merge>
<include layout="@layout/exo_simple_player_view"/>
</merge>
......@@ -41,7 +41,7 @@
</attr>
<attr name="show_shuffle_button" format="boolean"/>
<declare-styleable name="SimpleExoPlayerView">
<declare-styleable name="PlayerView">
<attr name="use_artwork" format="boolean"/>
<attr name="shutter_background_color" format="color"/>
<attr name="default_artwork" format="reference"/>
......@@ -52,7 +52,7 @@
<attr name="resize_mode"/>
<attr name="surface_type"/>
<attr name="player_layout_id"/>
<!-- PlaybackControlView attrs -->
<!-- PlayerControlView attributes -->
<attr name="show_timeout"/>
<attr name="rewind_increment"/>
<attr name="fastforward_increment"/>
......@@ -65,7 +65,7 @@
<attr name="resize_mode"/>
</declare-styleable>
<declare-styleable name="PlaybackControlView">
<declare-styleable name="PlayerControlView">
<attr name="show_timeout"/>
<attr name="rewind_increment"/>
<attr name="fastforward_increment"/>
......
......@@ -32,6 +32,16 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
*/
public abstract class StubExoPlayer implements ExoPlayer {
@Override
public VideoComponent getVideoComponent() {
throw new UnsupportedOperationException();
}
@Override
public TextComponent getTextComponent() {
throw new UnsupportedOperationException();
}
@Override
public Looper getPlaybackLooper() {
throw new UnsupportedOperationException();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册