Support multiple video/text/metadata outputs
We've seen more than one issue filed where a developer has registered a video listener and been confused by the fact their SimpleExoPlayerView no longer works properly. There are also valid use cases for having multiple metadata/text outputs. Issue: #2933 Issue: #2800 Issue: #2286 Issue: #2240 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=164839882
This commit is contained in:
parent
5ab0c620bf
commit
88bae5d975
@ -294,9 +294,9 @@ public class PlayerActivity extends Activity implements OnClickListener, EventLi
|
||||
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);
|
||||
player.addListener(this);
|
||||
player.addListener(eventLogger);
|
||||
player.addMetadataOutput(eventLogger);
|
||||
player.setAudioDebugListener(eventLogger);
|
||||
player.setVideoDebugListener(eventLogger);
|
||||
player.setMetadataOutput(eventLogger);
|
||||
|
||||
simpleExoPlayerView.setPlayer(player);
|
||||
player.setPlayWhenReady(shouldAutoPlay);
|
||||
|
@ -41,6 +41,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelector;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.android.exoplayer2.video.VideoRendererEventListener;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* An {@link ExoPlayer} implementation that uses default {@link Renderer} components. Instances can
|
||||
@ -87,6 +88,9 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
|
||||
private final ExoPlayer player;
|
||||
private final ComponentListener componentListener;
|
||||
private final CopyOnWriteArraySet<VideoListener> videoListeners;
|
||||
private final CopyOnWriteArraySet<TextRenderer.Output> textOutputs;
|
||||
private final CopyOnWriteArraySet<MetadataRenderer.Output> metadataOutputs;
|
||||
private final int videoRendererCount;
|
||||
private final int audioRendererCount;
|
||||
|
||||
@ -99,9 +103,6 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
private int videoScalingMode;
|
||||
private SurfaceHolder surfaceHolder;
|
||||
private TextureView textureView;
|
||||
private TextRenderer.Output textOutput;
|
||||
private MetadataRenderer.Output metadataOutput;
|
||||
private VideoListener videoListener;
|
||||
private AudioRendererEventListener audioDebugListener;
|
||||
private VideoRendererEventListener videoDebugListener;
|
||||
private DecoderCounters videoDecoderCounters;
|
||||
@ -113,6 +114,9 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
protected SimpleExoPlayer(RenderersFactory renderersFactory, TrackSelector trackSelector,
|
||||
LoadControl loadControl) {
|
||||
componentListener = new ComponentListener();
|
||||
videoListeners = new CopyOnWriteArraySet<>();
|
||||
textOutputs = new CopyOnWriteArraySet<>();
|
||||
metadataOutputs = new CopyOnWriteArraySet<>();
|
||||
Looper eventLooper = Looper.myLooper() != null ? Looper.myLooper() : Looper.getMainLooper();
|
||||
Handler eventHandler = new Handler(eventLooper);
|
||||
renderers = renderersFactory.createRenderers(eventHandler, componentListener, componentListener,
|
||||
@ -440,63 +444,132 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener to receive video events.
|
||||
* Adds a listener to receive video events.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
*/
|
||||
public void addVideoListener(VideoListener listener) {
|
||||
videoListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener of video events.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*/
|
||||
public void removeVideoListener(VideoListener listener) {
|
||||
videoListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener to receive video events, removing all existing listeners.
|
||||
*
|
||||
* @param listener The listener.
|
||||
* @deprecated Use {@link #addVideoListener(VideoListener)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setVideoListener(VideoListener listener) {
|
||||
videoListener = listener;
|
||||
videoListeners.clear();
|
||||
if (listener != null) {
|
||||
addVideoListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the listener receiving video events if it matches the one passed. Else does nothing.
|
||||
* Equivalent to {@link #removeVideoListener(VideoListener)}.
|
||||
*
|
||||
* @param listener The listener to clear.
|
||||
* @deprecated Use {@link #removeVideoListener(VideoListener)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void clearVideoListener(VideoListener listener) {
|
||||
if (videoListener == listener) {
|
||||
videoListener = null;
|
||||
}
|
||||
removeVideoListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an output to receive text events.
|
||||
* Registers an output to receive text events.
|
||||
*
|
||||
* @param listener The output to register.
|
||||
*/
|
||||
public void addTextOutput(TextRenderer.Output listener) {
|
||||
textOutputs.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a text output.
|
||||
*
|
||||
* @param listener The output to remove.
|
||||
*/
|
||||
public void removeTextOutput(TextRenderer.Output listener) {
|
||||
textOutputs.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an output to receive text events, removing all existing outputs.
|
||||
*
|
||||
* @param output The output.
|
||||
* @deprecated Use {@link #addTextOutput(TextRenderer.Output)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setTextOutput(TextRenderer.Output output) {
|
||||
textOutput = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the output receiving text events if it matches the one passed. Else does nothing.
|
||||
*
|
||||
* @param output The output to clear.
|
||||
*/
|
||||
public void clearTextOutput(TextRenderer.Output output) {
|
||||
if (textOutput == output) {
|
||||
textOutput = null;
|
||||
textOutputs.clear();
|
||||
if (output != null) {
|
||||
addTextOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener to receive metadata events.
|
||||
* Equivalent to {@link #removeTextOutput(TextRenderer.Output)}.
|
||||
*
|
||||
* @param output The output to clear.
|
||||
* @deprecated Use {@link #removeTextOutput(TextRenderer.Output)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void clearTextOutput(TextRenderer.Output output) {
|
||||
removeTextOutput(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an output to receive metadata events.
|
||||
*
|
||||
* @param listener The output to register.
|
||||
*/
|
||||
public void addMetadataOutput(MetadataRenderer.Output listener) {
|
||||
metadataOutputs.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a metadata output.
|
||||
*
|
||||
* @param listener The output to remove.
|
||||
*/
|
||||
public void removeMetadataOutput(MetadataRenderer.Output listener) {
|
||||
metadataOutputs.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an output to receive metadata events, removing all existing outputs.
|
||||
*
|
||||
* @param output The output.
|
||||
* @deprecated Use {@link #addMetadataOutput(MetadataRenderer.Output)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setMetadataOutput(MetadataRenderer.Output output) {
|
||||
metadataOutput = output;
|
||||
metadataOutputs.clear();
|
||||
if (output != null) {
|
||||
addMetadataOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the output receiving metadata events if it matches the one passed. Else does nothing.
|
||||
* Equivalent to {@link #removeMetadataOutput(MetadataRenderer.Output)}.
|
||||
*
|
||||
* @param output The output to clear.
|
||||
* @deprecated Use {@link #removeMetadataOutput(MetadataRenderer.Output)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void clearMetadataOutput(MetadataRenderer.Output output) {
|
||||
if (metadataOutput == output) {
|
||||
metadataOutput = null;
|
||||
}
|
||||
removeMetadataOutput(output);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -816,7 +889,7 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
@Override
|
||||
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
|
||||
float pixelWidthHeightRatio) {
|
||||
if (videoListener != null) {
|
||||
for (VideoListener videoListener : videoListeners) {
|
||||
videoListener.onVideoSizeChanged(width, height, unappliedRotationDegrees,
|
||||
pixelWidthHeightRatio);
|
||||
}
|
||||
@ -828,8 +901,10 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
|
||||
@Override
|
||||
public void onRenderedFirstFrame(Surface surface) {
|
||||
if (videoListener != null && SimpleExoPlayer.this.surface == surface) {
|
||||
videoListener.onRenderedFirstFrame();
|
||||
if (SimpleExoPlayer.this.surface == surface) {
|
||||
for (VideoListener videoListener : videoListeners) {
|
||||
videoListener.onRenderedFirstFrame();
|
||||
}
|
||||
}
|
||||
if (videoDebugListener != null) {
|
||||
videoDebugListener.onRenderedFirstFrame(surface);
|
||||
@ -902,7 +977,7 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
|
||||
@Override
|
||||
public void onCues(List<Cue> cues) {
|
||||
if (textOutput != null) {
|
||||
for (TextRenderer.Output textOutput : textOutputs) {
|
||||
textOutput.onCues(cues);
|
||||
}
|
||||
}
|
||||
@ -911,7 +986,7 @@ public class SimpleExoPlayer implements ExoPlayer {
|
||||
|
||||
@Override
|
||||
public void onMetadata(Metadata metadata) {
|
||||
if (metadataOutput != null) {
|
||||
for (MetadataRenderer.Output metadataOutput : metadataOutputs) {
|
||||
metadataOutput.onMetadata(metadata);
|
||||
}
|
||||
}
|
||||
|
@ -379,9 +379,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and
|
||||
* {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous
|
||||
* assignments are overridden.
|
||||
* Set the {@link SimpleExoPlayer} to use.
|
||||
* <p>
|
||||
* To transition a {@link SimpleExoPlayer} from targeting one view to another, it's recommended to
|
||||
* use {@link #switchTargetView(SimpleExoPlayer, SimpleExoPlayerView, SimpleExoPlayerView)} rather
|
||||
@ -397,8 +395,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
}
|
||||
if (this.player != null) {
|
||||
this.player.removeListener(componentListener);
|
||||
this.player.clearTextOutput(componentListener);
|
||||
this.player.clearVideoListener(componentListener);
|
||||
this.player.removeTextOutput(componentListener);
|
||||
this.player.removeVideoListener(componentListener);
|
||||
if (surfaceView instanceof TextureView) {
|
||||
this.player.clearVideoTextureView((TextureView) surfaceView);
|
||||
} else if (surfaceView instanceof SurfaceView) {
|
||||
@ -418,8 +416,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
} else if (surfaceView instanceof SurfaceView) {
|
||||
player.setVideoSurfaceView((SurfaceView) surfaceView);
|
||||
}
|
||||
player.setVideoListener(componentListener);
|
||||
player.setTextOutput(componentListener);
|
||||
player.addVideoListener(componentListener);
|
||||
player.addTextOutput(componentListener);
|
||||
player.addListener(componentListener);
|
||||
maybeShowController(false);
|
||||
updateForCurrentTrackSelections();
|
||||
|
Loading…
x
Reference in New Issue
Block a user