FileDocCategorySizeDatePackage
SurfaceRenderFilter.javaAPI DocAndroid 5.1 API9785Thu Mar 12 22:22:30 GMT 2015android.filterpacks.ui

SurfaceRenderFilter

public class SurfaceRenderFilter extends android.filterfw.core.Filter implements SurfaceHolder.Callback
hide

Fields Summary
private final int
RENDERMODE_STRETCH
private final int
RENDERMODE_FIT
private final int
RENDERMODE_FILL_CROP
private android.filterfw.core.FilterSurfaceView
mSurfaceView
Required. Sets the destination filter surface view for this node.
private String
mRenderModeString
Optional. 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 voidclose(android.filterfw.core.FilterContext context)

        mSurfaceView.unbind();
    
public voidfieldPortValueUpdated(java.lang.String name, android.filterfw.core.FilterContext context)

        updateTargetRect();
    
public voidopen(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 voidprepare(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 voidprocess(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 voidsetupPorts()

        // 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 voidsurfaceChanged(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 voidsurfaceCreated(android.view.SurfaceHolder holder)

        mIsBound = true;
    
public synchronized voidsurfaceDestroyed(android.view.SurfaceHolder holder)

        mIsBound = false;
    
public voidtearDown(android.filterfw.core.FilterContext context)

        if (mScreen != null) {
            mScreen.release();
        }
    
public voidupdateRenderMode()

        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 voidupdateTargetRect()

        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;
            }
        }