SurfaceRenderFilterpublic class SurfaceRenderFilter extends android.filterfw.core.Filter implements SurfaceHolder.Callback
Fields Summary |
---|
private final int | RENDERMODE_STRETCH | private final int | RENDERMODE_FIT | private final int | RENDERMODE_FILL_CROP | private android.filterfw.core.FilterSurfaceView | mSurfaceViewRequired. Sets the destination filter surface view for this
node. | private String | mRenderModeStringOptional. Control how the incoming frames are rendered onto the
output. Default is FIT.
RENDERMODE_STRETCH: Just fill the output surfaceView.
RENDERMODE_FIT: Keep aspect ratio and fit without cropping. May
have black bars.
RENDERMODE_FILL_CROP: Keep aspect ratio and fit without black
bars. May crop. | private boolean | mIsBound | private android.filterfw.core.ShaderProgram | mProgram | private android.filterfw.core.GLFrame | mScreen | private int | mRenderMode | private float | mAspectRatio | private int | mScreenWidth | private int | mScreenHeight | private boolean | mLogVerbose | private static final String | TAG |
Constructors Summary |
---|
public SurfaceRenderFilter(String name)
super(name);
mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
|
Methods Summary |
---|
public void | close(android.filterfw.core.FilterContext context)
mSurfaceView.unbind();
| public void | fieldPortValueUpdated(java.lang.String name, android.filterfw.core.FilterContext context)
updateTargetRect();
| public void | open(android.filterfw.core.FilterContext context)
// Bind surface view to us. This will emit a surfaceCreated and surfaceChanged call that
// will update our screen width and height.
mSurfaceView.unbind();
mSurfaceView.bindToListener(this, context.getGLEnvironment());
| public void | prepare(android.filterfw.core.FilterContext context)
// Create identity shader to render, and make sure to render upside-down, as textures
// are stored internally bottom-to-top.
mProgram = ShaderProgram.createIdentity(context);
mProgram.setSourceRect(0, 1, 1, -1);
mProgram.setClearsOutput(true);
mProgram.setClearColor(0.0f, 0.0f, 0.0f);
updateRenderMode();
// Create a frame representing the screen
MutableFrameFormat screenFormat = ImageFormat.create(mSurfaceView.getWidth(),
mSurfaceView.getHeight(),
ImageFormat.COLORSPACE_RGBA,
FrameFormat.TARGET_GPU);
mScreen = (GLFrame)context.getFrameManager().newBoundFrame(screenFormat,
GLFrame.EXISTING_FBO_BINDING,
0);
| public void | process(android.filterfw.core.FilterContext context)
// Make sure we are bound to a surface before rendering
if (!mIsBound) {
Log.w("SurfaceRenderFilter",
this + ": Ignoring frame as there is no surface to render to!");
return;
}
if (mLogVerbose) Log.v(TAG, "Starting frame processing");
GLEnvironment glEnv = mSurfaceView.getGLEnv();
if (glEnv != context.getGLEnvironment()) {
throw new RuntimeException("Surface created under different GLEnvironment!");
}
// Get input frame
Frame input = pullInput("frame");
boolean createdFrame = false;
float currentAspectRatio = (float)input.getFormat().getWidth() / input.getFormat().getHeight();
if (currentAspectRatio != mAspectRatio) {
if (mLogVerbose) Log.v(TAG, "New aspect ratio: " + currentAspectRatio +", previously: " + mAspectRatio);
mAspectRatio = currentAspectRatio;
updateTargetRect();
}
// See if we need to copy to GPU
Frame gpuFrame = null;
if (mLogVerbose) Log.v("SurfaceRenderFilter", "Got input format: " + input.getFormat());
int target = input.getFormat().getTarget();
if (target != FrameFormat.TARGET_GPU) {
gpuFrame = context.getFrameManager().duplicateFrameToTarget(input,
FrameFormat.TARGET_GPU);
createdFrame = true;
} else {
gpuFrame = input;
}
// Activate our surface
glEnv.activateSurfaceWithId(mSurfaceView.getSurfaceId());
// Process
mProgram.process(gpuFrame, mScreen);
// And swap buffers
glEnv.swapBuffers();
if (createdFrame) {
gpuFrame.release();
}
| public void | setupPorts()
// Make sure we have a SurfaceView
if (mSurfaceView == null) {
throw new RuntimeException("NULL SurfaceView passed to SurfaceRenderFilter");
}
// Add input port
addMaskedInputPort("frame", ImageFormat.create(ImageFormat.COLORSPACE_RGBA));
| public synchronized void | surfaceChanged(android.view.SurfaceHolder holder, int format, int width, int height)
// If the screen is null, we do not care about surface changes (yet). Once we have a
// screen object, we need to keep track of these changes.
if (mScreen != null) {
mScreenWidth = width;
mScreenHeight = height;
mScreen.setViewport(0, 0, mScreenWidth, mScreenHeight);
updateTargetRect();
}
| public synchronized void | surfaceCreated(android.view.SurfaceHolder holder)
mIsBound = true;
| public synchronized void | surfaceDestroyed(android.view.SurfaceHolder holder)
mIsBound = false;
| public void | tearDown(android.filterfw.core.FilterContext context)
if (mScreen != null) {
mScreen.release();
}
| public void | updateRenderMode()
if (mRenderModeString != null) {
if (mRenderModeString.equals("stretch")) {
mRenderMode = RENDERMODE_STRETCH;
} else if (mRenderModeString.equals("fit")) {
mRenderMode = RENDERMODE_FIT;
} else if (mRenderModeString.equals("fill_crop")) {
mRenderMode = RENDERMODE_FILL_CROP;
} else {
throw new RuntimeException("Unknown render mode '" + mRenderModeString + "'!");
}
}
updateTargetRect();
| private void | updateTargetRect()
if (mScreenWidth > 0 && mScreenHeight > 0 && mProgram != null) {
float screenAspectRatio = (float)mScreenWidth / mScreenHeight;
float relativeAspectRatio = screenAspectRatio / mAspectRatio;
switch (mRenderMode) {
case RENDERMODE_STRETCH:
mProgram.setTargetRect(0, 0, 1, 1);
break;
case RENDERMODE_FIT:
if (relativeAspectRatio > 1.0f) {
// Screen is wider than the camera, scale down X
mProgram.setTargetRect(0.5f - 0.5f / relativeAspectRatio, 0.0f,
1.0f / relativeAspectRatio, 1.0f);
} else {
// Screen is taller than the camera, scale down Y
mProgram.setTargetRect(0.0f, 0.5f - 0.5f * relativeAspectRatio,
1.0f, relativeAspectRatio);
}
break;
case RENDERMODE_FILL_CROP:
if (relativeAspectRatio > 1) {
// Screen is wider than the camera, crop in Y
mProgram.setTargetRect(0.0f, 0.5f - 0.5f * relativeAspectRatio,
1.0f, relativeAspectRatio);
} else {
// Screen is taller than the camera, crop in X
mProgram.setTargetRect(0.5f - 0.5f / relativeAspectRatio, 0.0f,
1.0f / relativeAspectRatio, 1.0f);
}
break;
}
}
|
|