From 72f26d79f6f74e20f346fd400de4c4babe59ca5c Mon Sep 17 00:00:00 2001 From: Colin Kho Date: Thu, 5 Sep 2024 22:51:49 -0700 Subject: [PATCH] Added a forwarding class for Renderer to support composing custom behavior on Metadata & Text Renderers --- .../media3/exoplayer/ForwardingRenderer.java | 156 ++++++++++++++++++ .../audio/ForwardingRendererTest.java | 27 +++ 2 files changed, 183 insertions(+) create mode 100644 libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ForwardingRenderer.java create mode 100644 libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/ForwardingRendererTest.java diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ForwardingRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ForwardingRenderer.java new file mode 100644 index 0000000000..8996384c43 --- /dev/null +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ForwardingRenderer.java @@ -0,0 +1,156 @@ +package androidx.media3.exoplayer; + +import androidx.annotation.Nullable; +import androidx.media3.common.C; +import androidx.media3.common.Format; +import androidx.media3.common.Timeline; +import androidx.media3.common.util.Clock; +import androidx.media3.exoplayer.analytics.PlayerId; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.source.SampleStream; +import java.io.IOException; + +/** An overridable {@link ForwardingRenderer} implementation forwarding all methods to another renderer. */ +public class ForwardingRenderer implements Renderer { + + private final Renderer renderer; + + public ForwardingRenderer(Renderer renderer) { + this.renderer = renderer; + } + + @Override + public void handleMessage(@MessageType int messageType, @Nullable Object message) + throws ExoPlaybackException { + renderer.handleMessage(messageType, message); + } + + @Override + public String getName() { + return renderer.getName(); + } + + @Override + @C.TrackType + public int getTrackType() { + return renderer.getTrackType(); + } + + @Override + public RendererCapabilities getCapabilities() { + return renderer.getCapabilities(); + } + + @Override + public void init(int index, PlayerId playerId, Clock clock) { + renderer.init(index, playerId, clock); + } + + @Nullable + @Override + public MediaClock getMediaClock() { + return renderer.getMediaClock(); + } + + @Override + public @State int getState() { + return renderer.getState(); + } + + @Override + public void enable( + RendererConfiguration configuration, + Format[] formats, + SampleStream stream, + long positionUs, + boolean joining, + boolean mayRenderStartOfStream, + long startPositionUs, + long offsetUs, + MediaSource.MediaPeriodId mediaPeriodId) throws ExoPlaybackException { + renderer.enable(configuration, formats, stream, positionUs, joining, + mayRenderStartOfStream, startPositionUs, offsetUs, mediaPeriodId); + } + + @Override + public void start() throws ExoPlaybackException { + renderer.start(); + } + + @Override + public void replaceStream(Format[] formats, SampleStream stream, long startPositionUs, + long offsetUs, MediaSource.MediaPeriodId mediaPeriodId) throws ExoPlaybackException { + renderer.replaceStream(formats, stream, startPositionUs, offsetUs, mediaPeriodId); + } + + @Nullable + @Override + public SampleStream getStream() { + return renderer.getStream(); + } + + @Override + public boolean hasReadStreamToEnd() { + return renderer.hasReadStreamToEnd(); + } + + @Override + public long getReadingPositionUs() { + return renderer.getReadingPositionUs(); + } + + @Override + public void setCurrentStreamFinal() { + renderer.setCurrentStreamFinal(); + } + + @Override + public boolean isCurrentStreamFinal() { + return renderer.isCurrentStreamFinal(); + } + + @Override + public void maybeThrowStreamError() throws IOException { + renderer.maybeThrowStreamError(); + } + + @Override + public void resetPosition(long positionUs) throws ExoPlaybackException { + renderer.resetPosition(positionUs); + } + + @Override + public void setTimeline(Timeline timeline) { + + } + + @Override + public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { + renderer.render(positionUs, elapsedRealtimeUs); + } + + @Override + public boolean isReady() { + return renderer.isReady(); + } + + @Override + public boolean isEnded() { + return renderer.isEnded(); + } + + @Override + public void stop() { + renderer.stop(); + } + + @Override + public void disable() { + renderer.disable(); + } + + @Override + public void reset() { + renderer.reset(); + } +} diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/ForwardingRendererTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/ForwardingRendererTest.java new file mode 100644 index 0000000000..ed65e25137 --- /dev/null +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/ForwardingRendererTest.java @@ -0,0 +1,27 @@ +package androidx.media3.exoplayer.audio; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.media3.exoplayer.ForwardingRenderer; +import androidx.media3.exoplayer.Renderer; +import androidx.media3.test.utils.TestUtil; +import java.lang.reflect.Method; +import java.util.List; +import org.junit.Test; + +public class ForwardingRendererTest { + @Test + public void forwardingRenderer_overridesAllMethods() throws NoSuchMethodException { + // Check with reflection that ForwardingRenderer overrides all Renderer methods. + List methods = TestUtil.getPublicMethods(Renderer.class); + for (Method method : methods) { + if (!method.isDefault()) { + assertThat( + ForwardingRenderer.class + .getDeclaredMethod(method.getName(), method.getParameterTypes()) + .getDeclaringClass()) + .isEqualTo(ForwardingRenderer.class); + } + } + } +}