Effects: Output to texture without surface in VFP.
Allow the VideoFrameProcessor to output to a texture without an output surface. Tested by updating texture output tests to no longer output to a surface. PiperOrigin-RevId: 527244605
This commit is contained in:
parent
889f435a49
commit
97272c139c
@ -123,7 +123,8 @@ public interface VideoFrameProcessor {
|
|||||||
void onOutputSizeChanged(int width, int height);
|
void onOutputSizeChanged(int width, int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an output frame with the given {@code presentationTimeUs} becomes available.
|
* Called when an output frame with the given {@code presentationTimeUs} becomes available for
|
||||||
|
* rendering.
|
||||||
*
|
*
|
||||||
* @param presentationTimeUs The presentation time of the frame, in microseconds.
|
* @param presentationTimeUs The presentation time of the frame, in microseconds.
|
||||||
*/
|
*/
|
||||||
|
@ -114,6 +114,9 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
*
|
*
|
||||||
* <p>If set, the {@link VideoFrameProcessor} will output to an OpenGL texture, accessible via
|
* <p>If set, the {@link VideoFrameProcessor} will output to an OpenGL texture, accessible via
|
||||||
* {@link TextureOutputListener#onTextureRendered}. Otherwise, no texture will be rendered to.
|
* {@link TextureOutputListener#onTextureRendered}. Otherwise, no texture will be rendered to.
|
||||||
|
*
|
||||||
|
* <p>If an {@linkplain #setOutputSurfaceInfo output surface} is set, the texture output will
|
||||||
|
* be be adjusted as needed, to match the output surface's output.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@CanIgnoreReturnValue
|
@CanIgnoreReturnValue
|
||||||
|
@ -48,12 +48,13 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
|
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around a {@link DefaultShaderProgram} that writes to the provided output surface and if
|
* Wrapper around a {@link DefaultShaderProgram} that renders to the provided output surface or
|
||||||
* provided, the optional debug surface view or output texture.
|
* texture.
|
||||||
|
*
|
||||||
|
* <p>Also renders to a debug surface, if provided.
|
||||||
*
|
*
|
||||||
* <p>The wrapped {@link DefaultShaderProgram} applies the {@link GlMatrixTransformation} and {@link
|
* <p>The wrapped {@link DefaultShaderProgram} applies the {@link GlMatrixTransformation} and {@link
|
||||||
* RgbMatrix} instances passed to the constructor, followed by any transformations needed to convert
|
* RgbMatrix} instances passed to the constructor, followed by any transformations needed to convert
|
||||||
@ -92,15 +93,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private InputListener inputListener;
|
private InputListener inputListener;
|
||||||
private @MonotonicNonNull Size outputSizeBeforeSurfaceTransformation;
|
private @MonotonicNonNull Size outputSizeBeforeSurfaceTransformation;
|
||||||
@Nullable private SurfaceView debugSurfaceView;
|
@Nullable private SurfaceView debugSurfaceView;
|
||||||
private @MonotonicNonNull GlTextureInfo outputTexture;
|
@Nullable private GlTextureInfo outputTexture;
|
||||||
private boolean frameProcessingStarted;
|
private boolean frameProcessingStarted;
|
||||||
|
|
||||||
private volatile boolean outputChanged;
|
private volatile boolean outputSurfaceInfoChanged;
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
@Nullable
|
@Nullable
|
||||||
private SurfaceInfo outputSurfaceInfo;
|
private SurfaceInfo outputSurfaceInfo;
|
||||||
|
|
||||||
|
/** Wraps the {@link Surface} in {@link #outputSurfaceInfo}. */
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
@Nullable
|
@Nullable
|
||||||
private EGLSurface outputEglSurface;
|
private EGLSurface outputEglSurface;
|
||||||
@ -240,6 +242,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (outputTexture != null) {
|
if (outputTexture != null) {
|
||||||
|
GlTextureInfo outputTexture = checkNotNull(this.outputTexture);
|
||||||
GlUtil.deleteTexture(outputTexture.texId);
|
GlUtil.deleteTexture(outputTexture.texId);
|
||||||
GlUtil.deleteFbo(outputTexture.fboId);
|
GlUtil.deleteFbo(outputTexture.fboId);
|
||||||
}
|
}
|
||||||
@ -270,7 +273,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
this.outputEglSurface = null;
|
this.outputEglSurface = null;
|
||||||
}
|
}
|
||||||
outputChanged =
|
outputSurfaceInfoChanged =
|
||||||
this.outputSurfaceInfo == null
|
this.outputSurfaceInfo == null
|
||||||
|| outputSurfaceInfo == null
|
|| outputSurfaceInfo == null
|
||||||
|| this.outputSurfaceInfo.width != outputSurfaceInfo.width
|
|| this.outputSurfaceInfo.width != outputSurfaceInfo.width
|
||||||
@ -279,14 +282,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
this.outputSurfaceInfo = outputSurfaceInfo;
|
this.outputSurfaceInfo = outputSurfaceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFrame(
|
private synchronized void renderFrame(
|
||||||
GlTextureInfo inputTexture, long presentationTimeUs, long releaseTimeNs) {
|
GlTextureInfo inputTexture, long presentationTimeUs, long releaseTimeNs) {
|
||||||
try {
|
try {
|
||||||
maybeRenderFrameToOutputSurface(inputTexture, presentationTimeUs, releaseTimeNs);
|
if (releaseTimeNs == VideoFrameProcessor.DROP_OUTPUT_FRAME
|
||||||
if (textureOutputListener != null && defaultShaderProgram != null) {
|
|| !ensureConfigured(inputTexture.width, inputTexture.height)) {
|
||||||
|
inputListener.onInputFrameProcessed(inputTexture);
|
||||||
|
return; // Drop frames when requested, or there is no output surface.
|
||||||
|
}
|
||||||
|
if (outputSurfaceInfo != null) {
|
||||||
|
renderFrameToOutputSurface(inputTexture, presentationTimeUs, releaseTimeNs);
|
||||||
|
}
|
||||||
|
if (textureOutputListener != null) {
|
||||||
renderFrameToOutputTexture(inputTexture, presentationTimeUs);
|
renderFrameToOutputTexture(inputTexture, presentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (VideoFrameProcessingException | GlUtil.GlException e) {
|
} catch (VideoFrameProcessingException | GlUtil.GlException e) {
|
||||||
videoFrameProcessorListenerExecutor.execute(
|
videoFrameProcessorListenerExecutor.execute(
|
||||||
() ->
|
() ->
|
||||||
@ -300,17 +309,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
inputListener.onInputFrameProcessed(inputTexture);
|
inputListener.onInputFrameProcessed(inputTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void maybeRenderFrameToOutputSurface(
|
private synchronized void renderFrameToOutputSurface(
|
||||||
GlTextureInfo inputTexture, long presentationTimeUs, long releaseTimeNs)
|
GlTextureInfo inputTexture, long presentationTimeUs, long releaseTimeNs)
|
||||||
throws VideoFrameProcessingException, GlUtil.GlException {
|
throws VideoFrameProcessingException, GlUtil.GlException {
|
||||||
if (releaseTimeNs == VideoFrameProcessor.DROP_OUTPUT_FRAME
|
EGLSurface outputEglSurface = checkNotNull(this.outputEglSurface);
|
||||||
|| !ensureConfigured(inputTexture.width, inputTexture.height)) {
|
SurfaceInfo outputSurfaceInfo = checkNotNull(this.outputSurfaceInfo);
|
||||||
return; // Drop frames when requested, or there is no output surface.
|
DefaultShaderProgram defaultShaderProgram = checkNotNull(this.defaultShaderProgram);
|
||||||
}
|
|
||||||
|
|
||||||
EGLSurface outputEglSurface = this.outputEglSurface;
|
|
||||||
SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo;
|
|
||||||
DefaultShaderProgram defaultShaderProgram = this.defaultShaderProgram;
|
|
||||||
|
|
||||||
GlUtil.focusEglSurface(
|
GlUtil.focusEglSurface(
|
||||||
eglDisplay,
|
eglDisplay,
|
||||||
@ -332,7 +336,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
private void renderFrameToOutputTexture(GlTextureInfo inputTexture, long presentationTimeUs)
|
private void renderFrameToOutputTexture(GlTextureInfo inputTexture, long presentationTimeUs)
|
||||||
throws GlUtil.GlException, VideoFrameProcessingException {
|
throws GlUtil.GlException, VideoFrameProcessingException {
|
||||||
checkNotNull(outputTexture);
|
GlTextureInfo outputTexture = checkNotNull(this.outputTexture);
|
||||||
GlUtil.focusFramebufferUsingCurrentContext(
|
GlUtil.focusFramebufferUsingCurrentContext(
|
||||||
outputTexture.fboId, outputTexture.width, outputTexture.height);
|
outputTexture.fboId, outputTexture.width, outputTexture.height);
|
||||||
GlUtil.clearOutputFrame();
|
GlUtil.clearOutputFrame();
|
||||||
@ -345,12 +349,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
*
|
*
|
||||||
* <p>Returns {@code false} if {@code outputSurfaceInfo} is unset.
|
* <p>Returns {@code false} if {@code outputSurfaceInfo} is unset.
|
||||||
*/
|
*/
|
||||||
@EnsuresNonNullIf(
|
|
||||||
expression = {"outputSurfaceInfo", "outputEglSurface", "defaultShaderProgram"},
|
|
||||||
result = true)
|
|
||||||
private synchronized boolean ensureConfigured(int inputWidth, int inputHeight)
|
private synchronized boolean ensureConfigured(int inputWidth, int inputHeight)
|
||||||
throws VideoFrameProcessingException, GlUtil.GlException {
|
throws VideoFrameProcessingException, GlUtil.GlException {
|
||||||
|
// Clear extra or outdated resources.
|
||||||
boolean inputSizeChanged =
|
boolean inputSizeChanged =
|
||||||
this.inputWidth != inputWidth
|
this.inputWidth != inputWidth
|
||||||
|| this.inputHeight != inputHeight
|
|| this.inputHeight != inputHeight
|
||||||
@ -370,20 +371,31 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
outputSizeBeforeSurfaceTransformation.getHeight()));
|
outputSizeBeforeSurfaceTransformation.getHeight()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checkNotNull(outputSizeBeforeSurfaceTransformation);
|
||||||
|
|
||||||
if (outputSurfaceInfo == null) {
|
if (outputSurfaceInfo == null) {
|
||||||
|
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
|
||||||
|
outputEglSurface = null;
|
||||||
|
}
|
||||||
|
if (outputSurfaceInfo == null && textureOutputListener == null) {
|
||||||
if (defaultShaderProgram != null) {
|
if (defaultShaderProgram != null) {
|
||||||
defaultShaderProgram.release();
|
defaultShaderProgram.release();
|
||||||
defaultShaderProgram = null;
|
defaultShaderProgram = null;
|
||||||
}
|
}
|
||||||
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
|
|
||||||
outputEglSurface = null;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo;
|
int outputWidth =
|
||||||
@Nullable EGLSurface outputEglSurface = this.outputEglSurface;
|
outputSurfaceInfo == null
|
||||||
if (outputEglSurface == null) {
|
? outputSizeBeforeSurfaceTransformation.getWidth()
|
||||||
|
: outputSurfaceInfo.width;
|
||||||
|
int outputHeight =
|
||||||
|
outputSurfaceInfo == null
|
||||||
|
? outputSizeBeforeSurfaceTransformation.getHeight()
|
||||||
|
: outputSurfaceInfo.height;
|
||||||
|
|
||||||
|
// Allocate or update resources.
|
||||||
|
if (outputSurfaceInfo != null && outputEglSurface == null) {
|
||||||
outputEglSurface =
|
outputEglSurface =
|
||||||
glObjectsProvider.createEglSurface(
|
glObjectsProvider.createEglSurface(
|
||||||
eglDisplay,
|
eglDisplay,
|
||||||
@ -391,67 +403,58 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
outputColorInfo.colorTransfer,
|
outputColorInfo.colorTransfer,
|
||||||
// Frames are only released automatically when outputting to an encoder.
|
// Frames are only released automatically when outputting to an encoder.
|
||||||
/* isEncoderInputSurface= */ releaseFramesAutomatically);
|
/* isEncoderInputSurface= */ releaseFramesAutomatically);
|
||||||
|
|
||||||
@Nullable
|
|
||||||
SurfaceView debugSurfaceView =
|
|
||||||
debugViewProvider.getDebugPreviewSurfaceView(
|
|
||||||
outputSurfaceInfo.width, outputSurfaceInfo.height);
|
|
||||||
if (debugSurfaceView != null && !Util.areEqual(this.debugSurfaceView, debugSurfaceView)) {
|
|
||||||
debugSurfaceViewWrapper =
|
|
||||||
new SurfaceViewWrapper(
|
|
||||||
eglDisplay, eglContext, debugSurfaceView, outputColorInfo.colorTransfer);
|
|
||||||
}
|
|
||||||
this.debugSurfaceView = debugSurfaceView;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultShaderProgram != null && (outputChanged || inputSizeChanged)) {
|
@Nullable
|
||||||
|
SurfaceView debugSurfaceView =
|
||||||
|
debugViewProvider.getDebugPreviewSurfaceView(outputWidth, outputHeight);
|
||||||
|
if (debugSurfaceView != null && !Util.areEqual(this.debugSurfaceView, debugSurfaceView)) {
|
||||||
|
debugSurfaceViewWrapper =
|
||||||
|
new SurfaceViewWrapper(
|
||||||
|
eglDisplay, eglContext, debugSurfaceView, outputColorInfo.colorTransfer);
|
||||||
|
}
|
||||||
|
this.debugSurfaceView = debugSurfaceView;
|
||||||
|
|
||||||
|
if (textureOutputListener != null) {
|
||||||
|
int outputTexId =
|
||||||
|
GlUtil.createTexture(
|
||||||
|
outputWidth,
|
||||||
|
outputHeight,
|
||||||
|
/* useHighPrecisionColorComponents= */ ColorInfo.isTransferHdr(outputColorInfo));
|
||||||
|
outputTexture =
|
||||||
|
glObjectsProvider.createBuffersForTexture(outputTexId, outputWidth, outputHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultShaderProgram != null && (outputSurfaceInfoChanged || inputSizeChanged)) {
|
||||||
defaultShaderProgram.release();
|
defaultShaderProgram.release();
|
||||||
defaultShaderProgram = null;
|
defaultShaderProgram = null;
|
||||||
outputChanged = false;
|
outputSurfaceInfoChanged = false;
|
||||||
}
|
}
|
||||||
if (defaultShaderProgram == null) {
|
if (defaultShaderProgram == null) {
|
||||||
DefaultShaderProgram defaultShaderProgram =
|
defaultShaderProgram =
|
||||||
createDefaultShaderProgramForOutputSurface(outputSurfaceInfo);
|
createDefaultShaderProgram(
|
||||||
if (textureOutputListener != null) {
|
outputSurfaceInfo == null ? 0 : outputSurfaceInfo.orientationDegrees,
|
||||||
configureOutputTexture(
|
outputWidth,
|
||||||
checkNotNull(outputSizeBeforeSurfaceTransformation).getWidth(),
|
outputHeight);
|
||||||
checkNotNull(outputSizeBeforeSurfaceTransformation).getHeight());
|
|
||||||
}
|
|
||||||
this.defaultShaderProgram = defaultShaderProgram;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.outputSurfaceInfo = outputSurfaceInfo;
|
|
||||||
this.outputEglSurface = outputEglSurface;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureOutputTexture(int outputWidth, int outputHeight) throws GlUtil.GlException {
|
private synchronized DefaultShaderProgram createDefaultShaderProgram(
|
||||||
if (outputTexture != null) {
|
int outputOrientationDegrees, int outputWidth, int outputHeight)
|
||||||
GlUtil.deleteTexture(outputTexture.texId);
|
throws VideoFrameProcessingException {
|
||||||
GlUtil.deleteFbo(outputTexture.fboId);
|
|
||||||
}
|
|
||||||
int outputTexId =
|
|
||||||
GlUtil.createTexture(
|
|
||||||
outputWidth,
|
|
||||||
outputHeight,
|
|
||||||
/* useHighPrecisionColorComponents= */ ColorInfo.isTransferHdr(outputColorInfo));
|
|
||||||
outputTexture =
|
|
||||||
glObjectsProvider.createBuffersForTexture(outputTexId, outputWidth, outputHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DefaultShaderProgram createDefaultShaderProgramForOutputSurface(
|
|
||||||
SurfaceInfo outputSurfaceInfo) throws VideoFrameProcessingException {
|
|
||||||
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder =
|
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder =
|
||||||
new ImmutableList.Builder<GlMatrixTransformation>().addAll(matrixTransformations);
|
new ImmutableList.Builder<GlMatrixTransformation>().addAll(matrixTransformations);
|
||||||
if (outputSurfaceInfo.orientationDegrees != 0) {
|
if (outputOrientationDegrees != 0) {
|
||||||
matrixTransformationListBuilder.add(
|
matrixTransformationListBuilder.add(
|
||||||
new ScaleAndRotateTransformation.Builder()
|
new ScaleAndRotateTransformation.Builder()
|
||||||
.setRotationDegrees(outputSurfaceInfo.orientationDegrees)
|
.setRotationDegrees(outputOrientationDegrees)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
matrixTransformationListBuilder.add(
|
matrixTransformationListBuilder.add(
|
||||||
Presentation.createForWidthAndHeight(
|
Presentation.createForWidthAndHeight(
|
||||||
outputSurfaceInfo.width, outputSurfaceInfo.height, Presentation.LAYOUT_SCALE_TO_FIT));
|
outputWidth, outputHeight, Presentation.LAYOUT_SCALE_TO_FIT));
|
||||||
|
|
||||||
DefaultShaderProgram defaultShaderProgram;
|
DefaultShaderProgram defaultShaderProgram;
|
||||||
ImmutableList<GlMatrixTransformation> expandedMatrixTransformations =
|
ImmutableList<GlMatrixTransformation> expandedMatrixTransformations =
|
||||||
@ -488,8 +491,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
defaultShaderProgram.setTextureTransformMatrix(textureTransformMatrix);
|
defaultShaderProgram.setTextureTransformMatrix(textureTransformMatrix);
|
||||||
Size outputSize = defaultShaderProgram.configure(inputWidth, inputHeight);
|
Size outputSize = defaultShaderProgram.configure(inputWidth, inputHeight);
|
||||||
checkState(outputSize.getWidth() == outputSurfaceInfo.width);
|
if (outputSurfaceInfo != null) {
|
||||||
checkState(outputSize.getHeight() == outputSurfaceInfo.height);
|
SurfaceInfo outputSurfaceInfo = checkNotNull(this.outputSurfaceInfo);
|
||||||
|
checkState(outputSize.getWidth() == outputSurfaceInfo.width);
|
||||||
|
checkState(outputSize.getHeight() == outputSurfaceInfo.height);
|
||||||
|
}
|
||||||
return defaultShaderProgram;
|
return defaultShaderProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,14 +281,17 @@ public final class VideoFrameProcessorTestRunner {
|
|||||||
new VideoFrameProcessor.Listener() {
|
new VideoFrameProcessor.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onOutputSizeChanged(int width, int height) {
|
public void onOutputSizeChanged(int width, int height) {
|
||||||
|
@Nullable
|
||||||
Surface outputSurface =
|
Surface outputSurface =
|
||||||
bitmapReader.getSurface(
|
bitmapReader.getSurface(
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
/* useHighPrecisionColorComponents= */ ColorInfo.isTransferHdr(
|
/* useHighPrecisionColorComponents= */ ColorInfo.isTransferHdr(
|
||||||
outputColorInfo));
|
outputColorInfo));
|
||||||
checkNotNull(videoFrameProcessor)
|
if (outputSurface != null) {
|
||||||
.setOutputSurfaceInfo(new SurfaceInfo(outputSurface, width, height));
|
checkNotNull(videoFrameProcessor)
|
||||||
|
.setOutputSurfaceInfo(new SurfaceInfo(outputSurface, width, height));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -368,7 +371,8 @@ public final class VideoFrameProcessorTestRunner {
|
|||||||
/** Reads a {@link Bitmap} from {@link VideoFrameProcessor} output. */
|
/** Reads a {@link Bitmap} from {@link VideoFrameProcessor} output. */
|
||||||
public interface BitmapReader {
|
public interface BitmapReader {
|
||||||
|
|
||||||
/** Returns the {@link VideoFrameProcessor} output {@link Surface}. */
|
/** Returns the {@link VideoFrameProcessor} output {@link Surface}, if one is needed. */
|
||||||
|
@Nullable
|
||||||
Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents);
|
Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents);
|
||||||
|
|
||||||
/** Returns the output {@link Bitmap}. */
|
/** Returns the output {@link Bitmap}. */
|
||||||
@ -388,6 +392,7 @@ public final class VideoFrameProcessorTestRunner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressLint("WrongConstant")
|
@SuppressLint("WrongConstant")
|
||||||
|
@Nullable
|
||||||
public Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents) {
|
public Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents) {
|
||||||
imageReader =
|
imageReader =
|
||||||
ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, /* maxImages= */ 1);
|
ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, /* maxImages= */ 1);
|
||||||
|
@ -31,7 +31,6 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.SurfaceTexture;
|
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.media3.common.ColorInfo;
|
import androidx.media3.common.ColorInfo;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
@ -52,6 +51,7 @@ import androidx.media3.transformer.EncoderUtil;
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -306,16 +306,10 @@ public final class DefaultVideoFrameProcessorTextureOutputPixelTest {
|
|||||||
private @MonotonicNonNull Bitmap outputBitmap;
|
private @MonotonicNonNull Bitmap outputBitmap;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents) {
|
public Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents) {
|
||||||
this.useHighPrecisionColorComponents = useHighPrecisionColorComponents;
|
this.useHighPrecisionColorComponents = useHighPrecisionColorComponents;
|
||||||
int texId;
|
return null;
|
||||||
try {
|
|
||||||
texId = GlUtil.createExternalTexture();
|
|
||||||
} catch (GlUtil.GlException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
SurfaceTexture surfaceTexture = new SurfaceTexture(texId);
|
|
||||||
return new Surface(surfaceTexture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user