FileDocCategorySizeDatePackage
CameraSource.javaAPI DocAndroid 5.1 API13455Thu Mar 12 22:22:30 GMT 2015android.filterpacks.videosrc

CameraSource

public class CameraSource extends android.filterfw.core.Filter
hide

Fields Summary
private int
mCameraId
Camera ID to use for input. Defaults to 0.
private int
mWidth
Frame width to request from camera. Actual size may not match requested.
private int
mHeight
Frame height to request from camera. Actual size may not match requested.
private int
mFps
Stream framerate to request from camera. Actual frame rate may not match requested.
private boolean
mWaitForNewFrame
Whether the filter should always wait for a new frame from the camera before providing output. If set to false, the filter will keep outputting the last frame it received from the camera if multiple process calls are received before the next update from the Camera. Defaults to true.
private android.hardware.Camera
mCamera
private android.filterfw.core.GLFrame
mCameraFrame
private android.graphics.SurfaceTexture
mSurfaceTexture
private android.filterfw.core.ShaderProgram
mFrameExtractor
private android.filterfw.core.MutableFrameFormat
mOutputFormat
private float[]
mCameraTransform
private float[]
mMappedCoords
private static final float[]
mSourceCoords
private static final int
NEWFRAME_TIMEOUT
private static final int
NEWFRAME_TIMEOUT_REPEAT
private boolean
mNewFrameAvailable
private Camera.Parameters
mCameraParameters
private static final String
mFrameShader
private final boolean
mLogVerbose
private static final String
TAG
private SurfaceTexture.OnFrameAvailableListener
onCameraFrameAvailableListener
Constructors Summary
public CameraSource(String name)


       
        super(name);
        mCameraTransform = new float[16];
        mMappedCoords = new float[16];

        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
    
Methods Summary
public voidclose(android.filterfw.core.FilterContext context)

        if (mLogVerbose) Log.v(TAG, "Closing");

        mCamera.release();
        mCamera = 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("framerate")) {
            getCameraParameters();
            int closestRange[] = findClosestFpsRange(mFps, mCameraParameters);
            mCameraParameters.setPreviewFpsRange(closestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
                                                 closestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
            mCamera.setParameters(mCameraParameters);
        }
    
private int[]findClosestFpsRange(int fps, Camera.Parameters params)

        List<int[]> supportedFpsRanges = params.getSupportedPreviewFpsRange();
        int[] closestRange = supportedFpsRanges.get(0);
        for (int[] range : supportedFpsRanges) {
            if (range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] < fps*1000 &&
                range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] > fps*1000 &&
                range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] >
                closestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] &&
                range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] <
                closestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]) {
                closestRange = range;
            }
        }
        if (mLogVerbose) Log.v(TAG, "Requested fps: " + fps
                               + ".Closest frame rate range: ["
                               + closestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] / 1000.
                               + ","
                               + closestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] / 1000.
                               + "]");

        return closestRange;
    
private int[]findClosestSize(int width, int height, Camera.Parameters parameters)

        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        int closestWidth = -1;
        int closestHeight = -1;
        int smallestWidth = previewSizes.get(0).width;
        int smallestHeight =  previewSizes.get(0).height;
        for (Camera.Size size : previewSizes) {
            // Best match defined as not being larger in either dimension than
            // the requested size, but as close as possible. The below isn't a
            // stable selection (reording the size list can give different
            // results), but since this is a fallback nicety, that's acceptable.
            if ( size.width <= width &&
                 size.height <= height &&
                 size.width >= closestWidth &&
                 size.height >= closestHeight) {
                closestWidth = size.width;
                closestHeight = size.height;
            }
            if ( size.width < smallestWidth &&
                 size.height < smallestHeight) {
                smallestWidth = size.width;
                smallestHeight = size.height;
            }
        }
        if (closestWidth == -1) {
            // Requested size is smaller than any listed size; match with smallest possible
            closestWidth = smallestWidth;
            closestHeight = smallestHeight;
        }

        if (mLogVerbose) {
            Log.v(TAG,
                  "Requested resolution: (" + width + ", " + height
                  + "). Closest match: (" + closestWidth + ", "
                  + closestHeight + ").");
        }
        int[] closestSize = {closestWidth, closestHeight};
        return closestSize;
    
public synchronized Camera.ParametersgetCameraParameters()

        boolean closeCamera = false;
        if (mCameraParameters == null) {
            if (mCamera == null) {
                mCamera = Camera.open(mCameraId);
                closeCamera = true;
            }
            mCameraParameters = mCamera.getParameters();

            if (closeCamera) {
                mCamera.release();
                mCamera = null;
            }
        }

        int closestSize[] = findClosestSize(mWidth, mHeight, mCameraParameters);
        mWidth = closestSize[0];
        mHeight = closestSize[1];
        mCameraParameters.setPreviewSize(mWidth, mHeight);

        int closestRange[] = findClosestFpsRange(mFps, mCameraParameters);

        mCameraParameters.setPreviewFpsRange(closestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
                                             closestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);

        return mCameraParameters;
    
public voidopen(android.filterfw.core.FilterContext context)

        if (mLogVerbose) Log.v(TAG, "Opening");
        // Open camera
        mCamera = Camera.open(mCameraId);

        // Set parameters
        getCameraParameters();
        mCamera.setParameters(mCameraParameters);

        // Create frame formats
        createFormats();

        // Bind it to our camera frame
        mCameraFrame = (GLFrame)context.getFrameManager().newBoundFrame(mOutputFormat,
                                                                        GLFrame.EXTERNAL_TEXTURE,
                                                                        0);
        mSurfaceTexture = new SurfaceTexture(mCameraFrame.getTextureId());
        try {
            mCamera.setPreviewTexture(mSurfaceTexture);
        } catch (IOException e) {
            throw new RuntimeException("Could not bind camera surface texture: " +
                                       e.getMessage() + "!");
        }

        // Connect SurfaceTexture to callback
        mSurfaceTexture.setOnFrameAvailableListener(onCameraFrameAvailableListener);
        // Start the preview
        mNewFrameAvailable = false;
        mCamera.startPreview();
    
public voidprepare(android.filterfw.core.FilterContext context)

        if (mLogVerbose) Log.v(TAG, "Preparing");
        // Compile shader TODO: Move to onGLEnvSomething?
        mFrameExtractor = new ShaderProgram(context, mFrameShader);
    
public voidprocess(android.filterfw.core.FilterContext context)

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

        if (mWaitForNewFrame) {
            int waitCount = 0;
            while (!mNewFrameAvailable) {
                if (waitCount == NEWFRAME_TIMEOUT_REPEAT) {
                    throw new RuntimeException("Timeout waiting for new frame");
                }
                try {
                    this.wait(NEWFRAME_TIMEOUT);
                } catch (InterruptedException e) {
                    if (mLogVerbose) Log.v(TAG, "Interrupted while waiting for new frame");
                }
            }
            mNewFrameAvailable = false;
            if (mLogVerbose) Log.v(TAG, "Got new frame");
        }

        mSurfaceTexture.updateTexImage();

        if (mLogVerbose) Log.v(TAG, "Using frame extractor in thread: " + Thread.currentThread());
        mSurfaceTexture.getTransformMatrix(mCameraTransform);
        Matrix.multiplyMM(mMappedCoords, 0,
                          mCameraTransform, 0,
                          mSourceCoords, 0);
        mFrameExtractor.setSourceRegion(mMappedCoords[0], mMappedCoords[1],
                                        mMappedCoords[4], mMappedCoords[5],
                                        mMappedCoords[8], mMappedCoords[9],
                                        mMappedCoords[12], mMappedCoords[13]);

        Frame output = context.getFrameManager().newFrame(mOutputFormat);
        mFrameExtractor.process(mCameraFrame, output);

        long timestamp = mSurfaceTexture.getTimestamp();
        if (mLogVerbose) Log.v(TAG, "Timestamp: " + (timestamp / 1000000000.0) + " s");
        output.setTimestamp(timestamp);

        pushOutput("video", output);

        // Release pushed frame
        output.release();

        if (mLogVerbose) Log.v(TAG, "Done processing new frame");
    
public synchronized voidsetCameraParameters(Camera.Parameters params)
Update camera parameters. Image resolution cannot be changed.

        params.setPreviewSize(mWidth, mHeight);
        mCameraParameters = params;
        if (isOpen()) {
            mCamera.setParameters(mCameraParameters);
        }
    
public voidsetupPorts()

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

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