Skip to content

Commit

Permalink
Support multiple video/text/metadata outputs
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ojw28 authored and Oliver Woodman committed Sep 8, 2017
1 parent cf6c247 commit 99f603c
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,9 @@ private void initializePlayer() {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
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
Expand Down Expand Up @@ -87,6 +88,9 @@ void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,

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;

Expand All @@ -99,9 +103,6 @@ void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
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;
Expand All @@ -113,6 +114,9 @@ void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
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,
Expand Down Expand Up @@ -440,63 +444,132 @@ public DecoderCounters getAudioDecoderCounters() {
}

/**
* 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);
}

/**
* 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.
* 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;
textOutputs.clear();
if (output != null) {
addTextOutput(output);
}
}

/**
* Clears the output receiving text events if it matches the one passed. Else does nothing.
* 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) {
if (textOutput == output) {
textOutput = null;
}
removeTextOutput(output);
}

/**
* Sets a listener to receive metadata events.
* 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);
}

/**
Expand Down Expand Up @@ -803,7 +876,7 @@ public void onDroppedFrames(int count, long elapsed) {
@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);
}
Expand All @@ -815,8 +888,10 @@ public void onVideoSizeChanged(int width, int height, int unappliedRotationDegre

@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);
Expand Down Expand Up @@ -889,7 +964,7 @@ public void onAudioDisabled(DecoderCounters counters) {

@Override
public void onCues(List<Cue> cues) {
if (textOutput != null) {
for (TextRenderer.Output textOutput : textOutputs) {
textOutput.onCues(cues);
}
}
Expand All @@ -898,7 +973,7 @@ public void onCues(List<Cue> cues) {

@Override
public void onMetadata(Metadata metadata) {
if (metadataOutput != null) {
for (MetadataRenderer.Output metadataOutput : metadataOutputs) {
metadataOutput.onMetadata(metadata);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,7 @@ public SimpleExoPlayer getPlayer() {
}

/**
* 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
Expand All @@ -397,8 +395,8 @@ public void setPlayer(SimpleExoPlayer player) {
}
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) {
Expand All @@ -418,8 +416,8 @@ public void setPlayer(SimpleExoPlayer player) {
} 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();
Expand Down

0 comments on commit 99f603c

Please sign in to comment.