mirror of
https://github.com/androidx/media.git
synced 2025-05-18 04:59:54 +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 androidx.media3.transformer.AndroidTestUtil.MP4_ASSET;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
import static org.junit.Assert.assertThrows;
|
||||||
|
|
||||||
import android.app.Instrumentation;
|
import android.app.Instrumentation;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.opengl.EGLContext;
|
||||||
|
import android.opengl.EGLDisplay;
|
||||||
|
import android.opengl.EGLSurface;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
@ -33,8 +37,11 @@ import androidx.media3.common.ColorInfo;
|
|||||||
import androidx.media3.common.DebugViewProvider;
|
import androidx.media3.common.DebugViewProvider;
|
||||||
import androidx.media3.common.Effect;
|
import androidx.media3.common.Effect;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
|
import androidx.media3.common.GlObjectsProvider;
|
||||||
|
import androidx.media3.common.GlTextureInfo;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.MimeTypes;
|
import androidx.media3.common.MimeTypes;
|
||||||
|
import androidx.media3.common.PlaybackException;
|
||||||
import androidx.media3.common.VideoCompositorSettings;
|
import androidx.media3.common.VideoCompositorSettings;
|
||||||
import androidx.media3.common.VideoGraph;
|
import androidx.media3.common.VideoGraph;
|
||||||
import androidx.media3.common.audio.AudioProcessor;
|
import androidx.media3.common.audio.AudioProcessor;
|
||||||
@ -449,6 +456,66 @@ public class CompositionPlayerTest {
|
|||||||
listener.waitUntilPlayerEnded();
|
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
|
@Test
|
||||||
public void release_videoGraphWrapperFailsDuringRelease_playerDoesNotRaiseError()
|
public void release_videoGraphWrapperFailsDuringRelease_playerDoesNotRaiseError()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -38,6 +38,7 @@ import androidx.annotation.RestrictTo;
|
|||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Effect;
|
import androidx.media3.common.Effect;
|
||||||
|
import androidx.media3.common.GlObjectsProvider;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.PlaybackException;
|
import androidx.media3.common.PlaybackException;
|
||||||
import androidx.media3.common.Player;
|
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.Size;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
|
import androidx.media3.effect.DefaultGlObjectsProvider;
|
||||||
import androidx.media3.effect.DefaultVideoFrameProcessor;
|
import androidx.media3.effect.DefaultVideoFrameProcessor;
|
||||||
import androidx.media3.effect.SingleInputVideoGraph;
|
import androidx.media3.effect.SingleInputVideoGraph;
|
||||||
import androidx.media3.effect.TimestampAdjustment;
|
import androidx.media3.effect.TimestampAdjustment;
|
||||||
@ -128,6 +130,8 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
private boolean videoPrewarmingEnabled;
|
private boolean videoPrewarmingEnabled;
|
||||||
private Clock clock;
|
private Clock clock;
|
||||||
private VideoGraph.@MonotonicNonNull Factory videoGraphFactory;
|
private VideoGraph.@MonotonicNonNull Factory videoGraphFactory;
|
||||||
|
|
||||||
|
private @MonotonicNonNull GlObjectsProvider glObjectsProvider;
|
||||||
private boolean enableReplayableCache;
|
private boolean enableReplayableCache;
|
||||||
private boolean built;
|
private boolean built;
|
||||||
|
|
||||||
@ -250,6 +254,22 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
return this;
|
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.
|
* Sets whether to enable replayable cache.
|
||||||
*
|
*
|
||||||
@ -281,11 +301,14 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
audioSink = new DefaultAudioSink.Builder(context).build();
|
audioSink = new DefaultAudioSink.Builder(context).build();
|
||||||
}
|
}
|
||||||
if (videoGraphFactory == null) {
|
if (videoGraphFactory == null) {
|
||||||
videoGraphFactory =
|
DefaultVideoFrameProcessor.Factory.Builder videoFrameProcessorFactoryBuilder =
|
||||||
new SingleInputVideoGraph.Factory(
|
|
||||||
new DefaultVideoFrameProcessor.Factory.Builder()
|
new DefaultVideoFrameProcessor.Factory.Builder()
|
||||||
.setEnableReplayableCache(enableReplayableCache)
|
.setEnableReplayableCache(enableReplayableCache);
|
||||||
.build());
|
if (glObjectsProvider != null) {
|
||||||
|
videoFrameProcessorFactoryBuilder.setGlObjectsProvider(glObjectsProvider);
|
||||||
|
}
|
||||||
|
videoGraphFactory =
|
||||||
|
new SingleInputVideoGraph.Factory(videoFrameProcessorFactoryBuilder.build());
|
||||||
}
|
}
|
||||||
CompositionPlayer compositionPlayer = new CompositionPlayer(this);
|
CompositionPlayer compositionPlayer = new CompositionPlayer(this);
|
||||||
AnalyticsCollector analyticsCollector = new DefaultAnalyticsCollector(clock);
|
AnalyticsCollector analyticsCollector = new DefaultAnalyticsCollector(clock);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user