CameraSourcepublic class CameraSource extends android.filterfw.core.Filter
Fields Summary |
---|
private int | mCameraIdCamera ID to use for input. Defaults to 0. | private int | mWidthFrame width to request from camera. Actual size may not match requested. | private int | mHeightFrame height to request from camera. Actual size may not match requested. | private int | mFpsStream framerate to request from camera. Actual frame rate may not match requested. | private boolean | mWaitForNewFrameWhether 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 void | close(android.filterfw.core.FilterContext context)
if (mLogVerbose) Log.v(TAG, "Closing");
mCamera.release();
mCamera = null;
mSurfaceTexture.release();
mSurfaceTexture = null;
| private void | createFormats()
mOutputFormat = ImageFormat.create(mWidth, mHeight,
ImageFormat.COLORSPACE_RGBA,
FrameFormat.TARGET_GPU);
| public void | fieldPortValueUpdated(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.Parameters | getCameraParameters()
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 void | open(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 void | prepare(android.filterfw.core.FilterContext context)
if (mLogVerbose) Log.v(TAG, "Preparing");
// Compile shader TODO: Move to onGLEnvSomething?
mFrameExtractor = new ShaderProgram(context, mFrameShader);
| public void | process(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 void | setCameraParameters(Camera.Parameters params)Update camera parameters. Image resolution cannot be changed.
params.setPreviewSize(mWidth, mHeight);
mCameraParameters = params;
if (isOpen()) {
mCamera.setParameters(mCameraParameters);
}
| public void | setupPorts()
// Add input port
addOutputPort("video", ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
FrameFormat.TARGET_GPU));
| public void | tearDown(android.filterfw.core.FilterContext context)
if (mCameraFrame != null) {
mCameraFrame.release();
}
|
|