FileDocCategorySizeDatePackage
SurfaceTextureSource.javaAPI DocAndroid 5.1 API10233Thu Mar 12 22:22:30 GMT 2015android.filterpacks.videosrc

SurfaceTextureSource

public class SurfaceTextureSource extends android.filterfw.core.Filter

A filter that converts textures from a SurfaceTexture object into frames for processing in the filter framework.

To use, connect up the sourceListener callback, and then when executing the graph, use the SurfaceTexture object passed to the callback to feed frames into the filter graph. For example, pass the SurfaceTexture into {#link android.hardware.Camera.setPreviewTexture(android.graphics.SurfaceTexture)}. This filter is intended for applications that need for flexibility than the CameraSource and MediaSource provide. Note that the application needs to provide width and height information for the SurfaceTextureSource, which it should obtain from wherever the SurfaceTexture data is coming from to avoid unnecessary resampling.

hide

Fields Summary
private SurfaceTextureSourceListener
mSourceListener
A callback to send the internal SurfaceTexture object to, once it is created. This callback will be called when the the filter graph is preparing to execute, but before any processing has actually taken place. The SurfaceTexture object passed to this callback is the only way to feed this filter. When the filter graph is shutting down, this callback will be called again with null as the source. This callback may be called from an arbitrary thread, so it should not assume it is running in the UI thread in particular.
private int
mWidth
The width of the output image frame. If the texture width for the SurfaceTexture source is known, use it here to minimize resampling.
private int
mHeight
The height of the output image frame. If the texture height for the SurfaceTexture source is known, use it here to minimize resampling.
private boolean
mWaitForNewFrame
Whether the filter will always wait for a new frame from its SurfaceTexture, or whether it will output an old frame again if a new frame isn't available. The filter will always wait for the first frame, to avoid outputting a blank frame. Defaults to true.
private int
mWaitTimeout
Maximum timeout before signaling error when waiting for a new frame. Set this to zero to disable the timeout and wait indefinitely. In milliseconds.
private boolean
mCloseOnTimeout
Whether a timeout is an exception-causing failure, or just causes the filter to close.
private android.filterfw.core.GLFrame
mMediaFrame
private android.filterfw.core.ShaderProgram
mFrameExtractor
private android.graphics.SurfaceTexture
mSurfaceTexture
private android.filterfw.core.MutableFrameFormat
mOutputFormat
private android.os.ConditionVariable
mNewFrameAvailable
private boolean
mFirstFrame
private float[]
mFrameTransform
private float[]
mMappedCoords
private static final float[]
mSourceCoords
private final String
mRenderShader
private static final String
TAG
private static final boolean
mLogVerbose
private SurfaceTexture.OnFrameAvailableListener
onFrameAvailableListener
Constructors Summary
public SurfaceTextureSource(String name)


       
        super(name);
        mNewFrameAvailable = new ConditionVariable();
        mFrameTransform = new float[16];
        mMappedCoords = new float[16];
    
Methods Summary
public voidclose(android.filterfw.core.FilterContext context)

        if (mLogVerbose) Log.v(TAG, "SurfaceTextureSource closed");
        mSourceListener.onSurfaceTextureSourceReady(null);
        mSurfaceTexture.release();
        mSurfaceTexture = null;
    
private voidcreateFormats()

        mOutputFormat = ImageFormat.create(mWidth, mHeight,
                                           ImageFormat.COLORSPACE_RGBA,
                                           FrameFormat.TARGET_GPU);
    
public voidfieldPortValueUpdated(java.lang.String name, android.filterfw.core.FilterContext context)

        if (name.equals("width") || name.equals("height") ) {
            mOutputFormat.setDimensions(mWidth, mHeight);
        }
    
public voidopen(android.filterfw.core.FilterContext context)

        if (mLogVerbose) Log.v(TAG, "Opening SurfaceTextureSource");
        // Create SurfaceTexture anew each time - it can use substantial memory.
        mSurfaceTexture = new SurfaceTexture(mMediaFrame.getTextureId());
        // Connect SurfaceTexture to callback
        mSurfaceTexture.setOnFrameAvailableListener(onFrameAvailableListener);
        // Connect SurfaceTexture to source
        mSourceListener.onSurfaceTextureSourceReady(mSurfaceTexture);
        mFirstFrame = true;
    
protected voidprepare(android.filterfw.core.FilterContext context)

        if (mLogVerbose) Log.v(TAG, "Preparing SurfaceTextureSource");

        createFormats();

        // Prepare input
        mMediaFrame = (GLFrame)context.getFrameManager().newBoundFrame(mOutputFormat,
                                                                       GLFrame.EXTERNAL_TEXTURE,
                                                                       0);

        // Prepare output
        mFrameExtractor = new ShaderProgram(context, mRenderShader);
    
public voidprocess(android.filterfw.core.FilterContext context)

        if (mLogVerbose) Log.v(TAG, "Processing new frame");

        // First, get new frame if available
        if (mWaitForNewFrame || mFirstFrame) {
            boolean gotNewFrame;
            if (mWaitTimeout != 0) {
                gotNewFrame = mNewFrameAvailable.block(mWaitTimeout);
                if (!gotNewFrame) {
                    if (!mCloseOnTimeout) {
                        throw new RuntimeException("Timeout waiting for new frame");
                    } else {
                        if (mLogVerbose) Log.v(TAG, "Timeout waiting for a new frame. Closing.");
                        closeOutputPort("video");
                        return;
                    }
                }
            } else {
                mNewFrameAvailable.block();
            }
            mNewFrameAvailable.close();
            mFirstFrame = false;
        }

        mSurfaceTexture.updateTexImage();

        mSurfaceTexture.getTransformMatrix(mFrameTransform);
        Matrix.multiplyMM(mMappedCoords, 0,
                          mFrameTransform, 0,
                          mSourceCoords, 0);
        mFrameExtractor.setSourceRegion(mMappedCoords[0], mMappedCoords[1],
                                        mMappedCoords[4], mMappedCoords[5],
                                        mMappedCoords[8], mMappedCoords[9],
                                        mMappedCoords[12], mMappedCoords[13]);
        // Next, render to output
        Frame output = context.getFrameManager().newFrame(mOutputFormat);
        mFrameExtractor.process(mMediaFrame, output);

        output.setTimestamp(mSurfaceTexture.getTimestamp());

        pushOutput("video", output);
        output.release();
    
public voidsetupPorts()

        // Add input port
        addOutputPort("video", ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
                                                  FrameFormat.TARGET_GPU));
    
public voidtearDown(android.filterfw.core.FilterContext context)

        if (mMediaFrame != null) {
            mMediaFrame.release();
        }