mirror of
https://github.com/androidx/media.git
synced 2025-05-17 20:49:53 +08:00
Allow setting a GlObjectsProvider on CompositionPlayer
PiperOrigin-RevId: 756300618
This commit is contained in:
parent
fd24449e7e
commit
e6af3e49ca
@ -20,10 +20,14 @@ import static androidx.media3.transformer.AndroidTestUtil.JPG_SINGLE_PIXEL_ASSET
|
||||
import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.opengl.EGLContext;
|
||||
import android.opengl.EGLDisplay;
|
||||
import android.opengl.EGLSurface;
|
||||
import android.util.Pair;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
@ -33,8 +37,11 @@ import androidx.media3.common.ColorInfo;
|
||||
import androidx.media3.common.DebugViewProvider;
|
||||
import androidx.media3.common.Effect;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.GlObjectsProvider;
|
||||
import androidx.media3.common.GlTextureInfo;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.PlaybackException;
|
||||
import androidx.media3.common.VideoCompositorSettings;
|
||||
import androidx.media3.common.VideoGraph;
|
||||
import androidx.media3.common.audio.AudioProcessor;
|
||||
@ -449,6 +456,66 @@ public class CompositionPlayerTest {
|
||||
listener.waitUntilPlayerEnded();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGlObjectsProvider_withFailingImplementation_throws() {
|
||||
PlayerTestListener listener = new PlayerTestListener(TEST_TIMEOUT_MS);
|
||||
EditedMediaItem video =
|
||||
new EditedMediaItem.Builder(MediaItem.fromUri(MP4_ASSET.uri))
|
||||
.setDurationUs(MP4_ASSET.videoDurationUs)
|
||||
.build();
|
||||
|
||||
instrumentation.runOnMainSync(
|
||||
() -> {
|
||||
compositionPlayer =
|
||||
new CompositionPlayer.Builder(applicationContext)
|
||||
.setGlObjectsProvider(
|
||||
new GlObjectsProvider() {
|
||||
@Override
|
||||
public EGLContext createEglContext(
|
||||
EGLDisplay eglDisplay, int openGlVersion, int[] configAttributes) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EGLSurface createEglSurface(
|
||||
EGLDisplay eglDisplay,
|
||||
Object surface,
|
||||
@C.ColorTransfer int colorTransfer,
|
||||
boolean isEncoderInputSurface) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EGLSurface createFocusedPlaceholderEglSurface(
|
||||
EGLContext eglContext, EGLDisplay eglDisplay) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlTextureInfo createBuffersForTexture(
|
||||
int texId, int width, int height) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(EGLDisplay eglDisplay) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
})
|
||||
.build();
|
||||
// Set a surface on the player even though there is no UI on this test. We need a surface
|
||||
// otherwise the player will skip/drop video frames.
|
||||
compositionPlayer.setVideoSurfaceView(surfaceView);
|
||||
compositionPlayer.addListener(listener);
|
||||
compositionPlayer.setComposition(
|
||||
new Composition.Builder(new EditedMediaItemSequence.Builder(video).build()).build());
|
||||
compositionPlayer.prepare();
|
||||
compositionPlayer.play();
|
||||
});
|
||||
|
||||
assertThrows(PlaybackException.class, listener::waitUntilPlayerEnded);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void release_videoGraphWrapperFailsDuringRelease_playerDoesNotRaiseError()
|
||||
throws Exception {
|
||||
|
@ -38,6 +38,7 @@ import androidx.annotation.RestrictTo;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.Effect;
|
||||
import androidx.media3.common.GlObjectsProvider;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.PlaybackException;
|
||||
import androidx.media3.common.Player;
|
||||
@ -53,6 +54,7 @@ import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.effect.DefaultGlObjectsProvider;
|
||||
import androidx.media3.effect.DefaultVideoFrameProcessor;
|
||||
import androidx.media3.effect.SingleInputVideoGraph;
|
||||
import androidx.media3.effect.TimestampAdjustment;
|
||||
@ -128,6 +130,8 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
private boolean videoPrewarmingEnabled;
|
||||
private Clock clock;
|
||||
private VideoGraph.@MonotonicNonNull Factory videoGraphFactory;
|
||||
|
||||
private @MonotonicNonNull GlObjectsProvider glObjectsProvider;
|
||||
private boolean enableReplayableCache;
|
||||
private boolean built;
|
||||
|
||||
@ -250,6 +254,22 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link GlObjectsProvider} to be used by the effect processing pipeline.
|
||||
*
|
||||
* <p>Setting a {@link GlObjectsProvider} is no-op if a {@link VideoGraph.Factory} is
|
||||
* {@linkplain #setVideoGraphFactory set}. By default, a {@link DefaultGlObjectsProvider} is
|
||||
* used.
|
||||
*
|
||||
* @param glObjectsProvider The {@link GlObjectsProvider}.
|
||||
* @return This builder, for convenience.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setGlObjectsProvider(GlObjectsProvider glObjectsProvider) {
|
||||
this.glObjectsProvider = glObjectsProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable replayable cache.
|
||||
*
|
||||
@ -281,11 +301,14 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
||||
audioSink = new DefaultAudioSink.Builder(context).build();
|
||||
}
|
||||
if (videoGraphFactory == null) {
|
||||
videoGraphFactory =
|
||||
new SingleInputVideoGraph.Factory(
|
||||
DefaultVideoFrameProcessor.Factory.Builder videoFrameProcessorFactoryBuilder =
|
||||
new DefaultVideoFrameProcessor.Factory.Builder()
|
||||
.setEnableReplayableCache(enableReplayableCache)
|
||||
.build());
|
||||
.setEnableReplayableCache(enableReplayableCache);
|
||||
if (glObjectsProvider != null) {
|
||||
videoFrameProcessorFactoryBuilder.setGlObjectsProvider(glObjectsProvider);
|
||||
}
|
||||
videoGraphFactory =
|
||||
new SingleInputVideoGraph.Factory(videoFrameProcessorFactoryBuilder.build());
|
||||
}
|
||||
CompositionPlayer compositionPlayer = new CompositionPlayer(this);
|
||||
AnalyticsCollector analyticsCollector = new DefaultAnalyticsCollector(clock);
|
||||
|
Loading…
x
Reference in New Issue
Block a user