Commit 47f4d905 by hschlueter Committed by tonihei

Use TransformationException for GL errors.

PiperOrigin-RevId: 418820557
parent a9edb207
...@@ -52,6 +52,9 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -52,6 +52,9 @@ import java.util.concurrent.atomic.AtomicInteger;
* @param outputSurface The {@link Surface}. * @param outputSurface The {@link Surface}.
* @param debugViewProvider Provider for optional debug views to show intermediate output. * @param debugViewProvider Provider for optional debug views to show intermediate output.
* @return A configured {@code FrameEditor}. * @return A configured {@code FrameEditor}.
* @throws TransformationException If the {@code pixelWidthHeightRatio} isn't 1, reading shader
* files fails, or an OpenGL error occurs while creating and configuring the OpenGL
* components.
*/ */
public static FrameEditor create( public static FrameEditor create(
Context context, Context context,
...@@ -63,30 +66,71 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -63,30 +66,71 @@ import java.util.concurrent.atomic.AtomicInteger;
Transformer.DebugViewProvider debugViewProvider) Transformer.DebugViewProvider debugViewProvider)
throws TransformationException { throws TransformationException {
if (pixelWidthHeightRatio != 1.0f) { if (pixelWidthHeightRatio != 1.0f) {
// TODO(http://b/211782176): Consider implementing support for non-square pixels. // TODO(b/211782176): Consider implementing support for non-square pixels.
throw new TransformationException( throw TransformationException.createForFrameEditor(
"FrameEditor Error", new UnsupportedOperationException(
new IllegalArgumentException(
"Transformer's frame editor currently does not support frame edits on non-square" "Transformer's frame editor currently does not support frame edits on non-square"
+ " pixels. The pixelWidthHeightRatio is: " + " pixels. The pixelWidthHeightRatio is: "
+ pixelWidthHeightRatio), + pixelWidthHeightRatio),
TransformationException.ERROR_CODE_GL_INIT_FAILED); TransformationException.ERROR_CODE_GL_INIT_FAILED);
} }
EGLDisplay eglDisplay = GlUtil.createEglDisplay(); @Nullable
EGLContext eglContext = GlUtil.createEglContext(eglDisplay); SurfaceView debugSurfaceView =
EGLSurface eglSurface = GlUtil.getEglSurface(eglDisplay, outputSurface); debugViewProvider.getDebugPreviewSurfaceView(outputWidth, outputHeight);
GlUtil.focusSurface(eglDisplay, eglContext, eglSurface, outputWidth, outputHeight);
int textureId = GlUtil.createExternalTexture(); EGLDisplay eglDisplay;
EGLContext eglContext;
EGLSurface eglSurface;
int textureId;
GlUtil.Program glProgram; GlUtil.Program glProgram;
@Nullable EGLSurface debugPreviewEglSurface;
try { try {
// TODO(internal b/205002913): check the loaded program is consistent with the attributes eglDisplay = GlUtil.createEglDisplay();
// and uniforms expected in the code. eglContext = GlUtil.createEglContext(eglDisplay);
glProgram = new GlUtil.Program(context, VERTEX_SHADER_FILE_PATH, FRAGMENT_SHADER_FILE_PATH); eglSurface = GlUtil.getEglSurface(eglDisplay, outputSurface);
} catch (IOException e) { GlUtil.focusSurface(eglDisplay, eglContext, eglSurface, outputWidth, outputHeight);
throw new IllegalStateException(e); textureId = GlUtil.createExternalTexture();
glProgram = configureGlProgram(context, transformationMatrix, textureId);
debugPreviewEglSurface =
debugSurfaceView == null
? null
: GlUtil.getEglSurface(eglDisplay, checkNotNull(debugSurfaceView.getHolder()));
} catch (IOException | GlUtil.GlException e) {
throw TransformationException.createForFrameEditor(
e, TransformationException.ERROR_CODE_GL_INIT_FAILED);
}
int debugPreviewWidth;
int debugPreviewHeight;
if (debugSurfaceView != null) {
debugPreviewWidth = debugSurfaceView.getWidth();
debugPreviewHeight = debugSurfaceView.getHeight();
} else {
debugPreviewWidth = C.LENGTH_UNSET;
debugPreviewHeight = C.LENGTH_UNSET;
} }
return new FrameEditor(
eglDisplay,
eglContext,
eglSurface,
textureId,
glProgram,
outputWidth,
outputHeight,
debugPreviewEglSurface,
debugPreviewWidth,
debugPreviewHeight);
}
private static GlUtil.Program configureGlProgram(
Context context, Matrix transformationMatrix, int textureId) throws IOException {
// TODO(b/205002913): check the loaded program is consistent with the attributes
// and uniforms expected in the code.
GlUtil.Program glProgram =
new GlUtil.Program(context, VERTEX_SHADER_FILE_PATH, FRAGMENT_SHADER_FILE_PATH);
glProgram.setBufferAttribute( glProgram.setBufferAttribute(
"aPosition", "aPosition",
new float[] { new float[] {
...@@ -109,34 +153,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -109,34 +153,7 @@ import java.util.concurrent.atomic.AtomicInteger;
float[] transformationMatrixArray = getGlMatrixArray(transformationMatrix); float[] transformationMatrixArray = getGlMatrixArray(transformationMatrix);
glProgram.setFloatsUniform("uTransformationMatrix", transformationMatrixArray); glProgram.setFloatsUniform("uTransformationMatrix", transformationMatrixArray);
return glProgram;
@Nullable
SurfaceView debugSurfaceView =
debugViewProvider.getDebugPreviewSurfaceView(outputWidth, outputHeight);
@Nullable EGLSurface debugPreviewEglSurface;
int debugPreviewWidth;
int debugPreviewHeight;
if (debugSurfaceView != null) {
debugPreviewEglSurface =
GlUtil.getEglSurface(eglDisplay, checkNotNull(debugSurfaceView.getHolder()));
debugPreviewWidth = debugSurfaceView.getWidth();
debugPreviewHeight = debugSurfaceView.getHeight();
} else {
debugPreviewEglSurface = null;
debugPreviewWidth = C.LENGTH_UNSET;
debugPreviewHeight = C.LENGTH_UNSET;
}
return new FrameEditor(
eglDisplay,
eglContext,
eglSurface,
textureId,
glProgram,
outputWidth,
outputHeight,
debugPreviewEglSurface,
debugPreviewWidth,
debugPreviewHeight);
} }
/** /**
...@@ -240,22 +257,31 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -240,22 +257,31 @@ import java.util.concurrent.atomic.AtomicInteger;
return pendingInputFrameCount.get() > 0; return pendingInputFrameCount.get() > 0;
} }
/** Processes pending input frame. */ /**
public void processData() { * Processes pending input frame.
inputSurfaceTexture.updateTexImage(); *
inputSurfaceTexture.getTransformMatrix(textureTransformMatrix); * @throws TransformationException If an OpenGL error occurs while processing the data.
glProgram.setFloatsUniform("uTexTransform", textureTransformMatrix); */
glProgram.bindAttributesAndUniforms(); public void processData() throws TransformationException {
try {
inputSurfaceTexture.updateTexImage();
inputSurfaceTexture.getTransformMatrix(textureTransformMatrix);
glProgram.setFloatsUniform("uTexTransform", textureTransformMatrix);
glProgram.bindAttributesAndUniforms();
focusAndDrawQuad(eglSurface, outputWidth, outputHeight); focusAndDrawQuad(eglSurface, outputWidth, outputHeight);
long surfaceTextureTimestampNs = inputSurfaceTexture.getTimestamp(); long surfaceTextureTimestampNs = inputSurfaceTexture.getTimestamp();
EGLExt.eglPresentationTimeANDROID(eglDisplay, eglSurface, surfaceTextureTimestampNs); EGLExt.eglPresentationTimeANDROID(eglDisplay, eglSurface, surfaceTextureTimestampNs);
EGL14.eglSwapBuffers(eglDisplay, eglSurface); EGL14.eglSwapBuffers(eglDisplay, eglSurface);
pendingInputFrameCount.decrementAndGet(); pendingInputFrameCount.decrementAndGet();
if (debugPreviewEglSurface != null) { if (debugPreviewEglSurface != null) {
focusAndDrawQuad(debugPreviewEglSurface, debugPreviewWidth, debugPreviewHeight); focusAndDrawQuad(debugPreviewEglSurface, debugPreviewWidth, debugPreviewHeight);
EGL14.eglSwapBuffers(eglDisplay, debugPreviewEglSurface); EGL14.eglSwapBuffers(eglDisplay, debugPreviewEglSurface);
}
} catch (GlUtil.GlException e) {
throw TransformationException.createForFrameEditor(
e, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED);
} }
} }
......
...@@ -229,7 +229,7 @@ public final class TransformationException extends Exception { ...@@ -229,7 +229,7 @@ public final class TransformationException extends Exception {
} }
/** /**
* Creates an instance for an audio processing related exception. * Creates an instance for an {@link AudioProcessor} related exception.
* *
* @param cause The cause of the failure. * @param cause The cause of the failure.
* @param componentName The name of the {@link AudioProcessor} used. * @param componentName The name of the {@link AudioProcessor} used.
...@@ -244,6 +244,18 @@ public final class TransformationException extends Exception { ...@@ -244,6 +244,18 @@ public final class TransformationException extends Exception {
} }
/** /**
* Creates an instance for a {@link FrameEditor} related exception.
*
* @param cause The cause of the failure.
* @param errorCode See {@link #errorCode}.
* @return The created instance.
*/
/* package */ static TransformationException createForFrameEditor(
Throwable cause, int errorCode) {
return new TransformationException("FrameEditor error", cause, errorCode);
}
/**
* Creates an instance for a muxer related exception. * Creates an instance for a muxer related exception.
* *
* @param cause The cause of the failure. * @param cause The cause of the failure.
......
...@@ -81,7 +81,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -81,7 +81,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
// The decoder rotates videos to their intended display orientation. The frameEditor rotates // The decoder rotates videos to their intended display orientation. The frameEditor rotates
// them back for improved encoder compatibility. // them back for improved encoder compatibility.
// TODO(internal b/201293185): After fragment shader transformations are implemented, put // TODO(b/201293185): After fragment shader transformations are implemented, put
// postrotation in a later vertex shader. // postrotation in a later vertex shader.
transformationRequest.transformationMatrix.postRotate(outputRotationDegrees); transformationRequest.transformationMatrix.postRotate(outputRotationDegrees);
...@@ -129,7 +129,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -129,7 +129,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Override @Override
public boolean processData() { public boolean processData() throws TransformationException {
if (decoder.isEnded()) { if (decoder.isEnded()) {
return false; return false;
} }
...@@ -155,7 +155,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -155,7 +155,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* Transformer}, using this method requires API level 29 or higher. * Transformer}, using this method requires API level 29 or higher.
*/ */
@RequiresApi(29) @RequiresApi(29)
private boolean processDataV29() { private boolean processDataV29() throws TransformationException {
if (frameEditor != null) { if (frameEditor != null) {
while (frameEditor.hasInputData()) { while (frameEditor.hasInputData()) {
// Processes as much frames in one invocation: FrameEditor's output surface will block // Processes as much frames in one invocation: FrameEditor's output surface will block
...@@ -170,7 +170,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -170,7 +170,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
if (decoder.isEnded()) { if (decoder.isEnded()) {
// TODO(internal b/208986865): Handle possible last frame drop. // TODO(b/208986865): Handle possible last frame drop.
encoder.signalEndOfInputStream(); encoder.signalEndOfInputStream();
return false; return false;
} }
...@@ -179,7 +179,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -179,7 +179,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
/** Processes input data. */ /** Processes input data. */
private boolean processDataDefault() { private boolean processDataDefault() throws TransformationException {
if (frameEditor != null) { if (frameEditor != null) {
if (frameEditor.hasInputData()) { if (frameEditor.hasInputData()) {
waitingForFrameEditorInput = false; waitingForFrameEditorInput = false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment