Add preview format and Size

pull/82/head
Mattia Iavarone 8 years ago
parent c0345f4e62
commit cc19729961
  1. 2
      README.md
  2. 2
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraCallbacksTest.java
  3. 8
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  4. 1
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  5. 7
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  6. 32
      cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java
  7. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/Size.java
  8. 24
      cameraview/src/test/java/com/otaliastudios/cameraview/FrameTest.java

@ -468,6 +468,8 @@ apply new data to it. So:
|`frame.getData()`|`byte[]`|The current preview frame, in its original orientation.|
|`frame.getTime()`|`long`|The preview timestamp, in `System.currentTimeMillis()` reference.|
|`frame.getRotation()`|`int`|The rotation that should be applied to the byte array in order to see what the user sees.|
|`frame.getSize()`|`Size`|The frame size, before any rotation is applied, to access data.|
|`frame.getFormat()`|`int`|The frame `ImageFormat`. This will always be `ImageFormat.NV_21` for now.|
|`frame.freeze()`|`Frame`|Clones this frame and makes it immutable. Can be expensive because requires copying the byte array.|
|`frame.release()`|`-`|Disposes the content of this frame. Should be used on frozen frames to release memory.|

@ -301,7 +301,7 @@ public class CameraCallbacksTest extends BaseTest {
@Test
public void testProcessFrame() {
completeTask().when(processor).process(any(Frame.class));
camera.mCameraCallbacks.dispatchFrame(new byte[]{0, 1, 2, 3}, 1000, 90);
camera.mCameraCallbacks.dispatchFrame(new byte[]{0, 1, 2, 3}, 1000, 90, new Size(1, 1), 0);
assertNotNull(task.await(200));
verify(processor, times(1)).process(any(Frame.class));

@ -143,6 +143,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback {
);
synchronized (mLock) {
Camera.Parameters params = mCamera.getParameters();
mPreviewFormat = params.getPreviewFormat();
params.setPreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); // <- not allowed during preview
params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); // <- allowed
mCamera.setParameters(params);
@ -478,7 +479,6 @@ class Camera1 extends CameraController implements Camera.PreviewCallback {
// Got to rotate the preview frame, since byte[] data here does not include
// EXIF tags automatically set by camera. So either we add EXIF, or we rotate.
// Adding EXIF to a byte array, unfortunately, is hard.
Camera.Parameters params = mCamera.getParameters();
final int sensorToDevice = computeExifRotation();
final int sensorToDisplay = computeSensorToDisplayOffset();
final boolean exifFlip = computeExifFlip();
@ -487,7 +487,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback {
final int preHeight = mPreviewSize.getHeight();
final int postWidth = flip ? preHeight : preWidth;
final int postHeight = flip ? preWidth : preHeight;
final int format = params.getPreviewFormat();
final int format = mPreviewFormat;
WorkerHandler.run(new Runnable() {
@Override
public void run() {
@ -509,7 +509,9 @@ class Camera1 extends CameraController implements Camera.PreviewCallback {
public void onPreviewFrame(byte[] data, Camera camera) {
mCameraCallbacks.dispatchFrame(data,
System.currentTimeMillis(),
computeExifRotation());
computeExifRotation(),
mPreviewSize,
mPreviewFormat);
}
@Override

@ -32,6 +32,7 @@ abstract class CameraController implements CameraPreview.SurfaceCallback {
protected Size mCaptureSize;
protected Size mPreviewSize;
protected int mPreviewFormat;
protected ExtraProperties mExtraProperties;
protected CameraOptions mOptions;

@ -1352,7 +1352,7 @@ public class CameraView extends FrameLayout {
void dispatchOnFocusEnd(@Nullable Gesture trigger, boolean success, PointF where);
void dispatchOnZoomChanged(final float newValue, final PointF[] fingers);
void dispatchOnExposureCorrectionChanged(float newValue, float[] bounds, PointF[] fingers);
void dispatchFrame(byte[] frame, long time, int rotation);
void dispatchFrame(byte[] frame, long time, int rotation, Size size, int previewFormat);
}
private class Callbacks implements CameraCallbacks {
@ -1605,14 +1605,15 @@ public class CameraView extends FrameLayout {
}
@Override
public void dispatchFrame(final byte[] frame, final long time, final int rotation) {
public void dispatchFrame(final byte[] frame, final long time, final int rotation,
final Size size, final int previewFormat) {
mLogger.i("dispatchFrame", time, rotation, "processors:", mFrameProcessors.size());
if (mFrameProcessors.isEmpty()) return;
if (mFrame == null) mFrame = new Frame();
mFrameProcessorsHandler.post(new Runnable() {
@Override
public void run() {
mFrame.set(frame, time, rotation);
mFrame.set(frame, time, rotation, size, previewFormat);
for (FrameProcessor processor : mFrameProcessors) {
processor.process(mFrame);
}

@ -8,13 +8,17 @@ public class Frame {
private byte[] mData = null;
private long mTime = -1;
private int mRotation = 0;
private Size mSize = null;
private int mFormat = -1;
Frame() {}
void set(byte[] data, long time, int rotation) {
void set(byte[] data, long time, int rotation, Size size, int format) {
this.mData = data;
this.mTime = time;
this.mRotation = rotation;
this.mSize = size;
this.mFormat = format;
}
@Override
@ -33,10 +37,8 @@ public class Frame {
public Frame freeze() {
byte[] data = new byte[mData.length];
System.arraycopy(mData, 0, data, 0, mData.length);
long time = mTime;
int rotation = mRotation;
Frame other = new Frame();
other.set(data, time, rotation);
other.set(data, mTime, mRotation, mSize, mFormat);
return other;
}
@ -48,6 +50,8 @@ public class Frame {
mData = null;
mRotation = 0;
mTime = -1;
mSize = null;
mFormat = -1;
}
/**
@ -78,4 +82,24 @@ public class Frame {
public int getRotation() {
return mRotation;
}
/**
* Returns the frame size.
*
* @return frame size
*/
public Size getSize() {
return mSize;
}
/**
* Returns the data format, in one of the
* {@link android.graphics.ImageFormat} constants.
*
* @return the data format
* @see android.graphics.ImageFormat
*/
public int getFormat() {
return mFormat;
}
}

@ -7,7 +7,7 @@ public class Size implements Comparable<Size> {
private final int mWidth;
private final int mHeight;
public Size(int width, int height) {
Size(int width, int height) {
mWidth = width;
mHeight = height;
}

@ -1,6 +1,8 @@
package com.otaliastudios.cameraview;
import android.graphics.ImageFormat;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
@ -16,31 +18,36 @@ public class FrameTest {
public void testDefaults() {
Frame frame = new Frame();
assertEquals(frame.getTime(), -1);
assertEquals(frame.getFormat(), -1);
assertEquals(frame.getRotation(), 0);
assertNull(frame.getData());
assertNull(frame.getSize());
}
@Test
public void testEquals() {
Frame f1 = new Frame();
f1.set(null, 1000, 90);
long time = 1000;
f1.set(null, time, 90, null, ImageFormat.NV21);
Frame f2 = new Frame();
f2.set(new byte[2], 1000, 0);
f2.set(new byte[2], time, 0, new Size(10, 10), ImageFormat.NV21);
assertEquals(f1, f2);
f2.set(new byte[2], 1001, 0);
f2.set(new byte[2], time + 1, 0, new Size(10, 10), ImageFormat.NV21);
assertNotEquals(f1, f2);
}
@Test
public void testRelease() {
Frame frame = new Frame();
frame.set(new byte[2], 1000, 90);
frame.set(new byte[2], 1000, 90, new Size(10, 10), ImageFormat.NV21);
frame.release();
assertEquals(frame.getTime(), -1);
assertEquals(frame.getFormat(), -1);
assertEquals(frame.getRotation(), 0);
assertNull(frame.getData());
assertNull(frame.getSize());
}
@Test
@ -49,18 +56,23 @@ public class FrameTest {
byte[] data = new byte[]{0, 1, 5, 0, 7, 3, 4, 5};
long time = 1000;
int rotation = 90;
frame.set(data, time, rotation);
Size size = new Size(10, 10);
int format = ImageFormat.NV21;
frame.set(data, time, rotation, size, format);
Frame frozen = frame.freeze();
assertArrayEquals(data, frozen.getData());
assertEquals(time, frozen.getTime());
assertEquals(rotation, frozen.getRotation());
assertEquals(size, frozen.getSize());
// Mutate the first, ensure that frozen is not affected
frame.set(new byte[]{3, 2, 1}, 50, 180);
frame.set(new byte[]{3, 2, 1}, 50, 180, new Size(1, 1), ImageFormat.JPEG);
assertArrayEquals(data, frozen.getData());
assertEquals(time, frozen.getTime());
assertEquals(rotation, frozen.getRotation());
assertEquals(size, frozen.getSize());
assertEquals(format, frozen.getFormat());
}
}

Loading…
Cancel
Save