diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 82772168..38252e2c 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -1563,65 +1563,5 @@ public class CameraView extends FrameLayout { //region Deprecated - /** - * This does nothing. - * @deprecated - * @param focus no-op - */ - @Deprecated - public void setFocus(int focus) { - } - - - /** - * This does nothing. - * @return no-op - * @deprecated - */ - @Deprecated - public int getFocus() { - return 0; - } - - - /** - * This does nothing. - * @deprecated - * @param method no-op - */ - @Deprecated - public void setCaptureMethod(int method) {} - - - /** - * This does nothing. - * @deprecated - * @param permissions no-op - */ - @Deprecated - public void setPermissionPolicy(int permissions) {} - - - /** - * Sets the zoom mode for the current session. - * - * @param zoom no-op - * @deprecated use {@link #mapGesture(Gesture, GestureAction)} to map zoom control to gestures - */ - @Deprecated - public void setZoomMode(int zoom) { - } - - - /** - * Gets the current zoom mode. - * @return no-op - * @deprecated use {@link #mapGesture(Gesture, GestureAction)} to map zoom control to gestures - */ - @Deprecated - public int getZoomMode() { - return 0; - } - //endregion } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java new file mode 100644 index 00000000..af3fb051 --- /dev/null +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java @@ -0,0 +1,81 @@ +package com.otaliastudios.cameraview; + +/** + * A preview frame to be processed by {@link FrameProcessor}s. + */ +public class Frame { + + private byte[] mData = null; + private long mTime = -1; + private int mRotation = 0; + + Frame() {} + + void set(byte[] data, long time, int rotation) { + this.mData = data; + this.mTime = time; + this.mRotation = rotation; + } + + @Override + public boolean equals(Object obj) { + // We want a super fast implementation here, do not compare arrays. + return obj instanceof Frame && ((Frame) obj).mTime == mTime; + } + + /** + * Clones the frame, returning a frozen content that will not be overwritten. + * This can be kept or safely passed to other threads. + * Using freeze without clearing with {@link #clear()} can result in memory leaks. + * + * @return a frozen 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); + return other; + } + + /** + * Disposes the contents of this frame. Can be useful for frozen frames + * that are not useful anymore. + */ + public void clear() { + mData = null; + mRotation = 0; + mTime = -1; + } + + /** + * Returns the frame data. + * @return the frame data + */ + public byte[] getData() { + return mData; + } + + /** + * Returns the milliseconds epoch for this frame, + * in the {@link System#currentTimeMillis()} reference. + * + * @return time data + */ + public long getTime() { + return mTime; + } + + /** + * Returns the clock-wise rotation that should be applied on the data + * array, such that the resulting frame matches what the user is seeing + * on screen. + * + * @return clock-wise rotation + */ + public int getRotation() { + return mRotation; + } +} diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/FrameProcessor.java b/cameraview/src/main/java/com/otaliastudios/cameraview/FrameProcessor.java new file mode 100644 index 00000000..0a3110b6 --- /dev/null +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/FrameProcessor.java @@ -0,0 +1,24 @@ +package com.otaliastudios.cameraview; + +import android.support.annotation.NonNull; +import android.support.annotation.WorkerThread; + +/** + * A FrameProcessor will process {@link Frame}s coming from the camera preview. + * It must be passed to {@link Cameraview#setFrameProcessor(FrameProcessor)}. + */ +public interface FrameProcessor { + + /** + * Processes the given frame. The frame will hold the correct values only for the + * duration of this method. When it returns, the frame contents will be replaced. + * + * To keep working with the Frame in an async manner, please use {@link Frame#freeze()}, + * which will return an immutable Frame. In that case you can pass / hold the frame for + * as long as you want, and then release its contents using {@link Frame#clear()}. + * + * @param frame the new frame + */ + @WorkerThread + void process(@NonNull Frame frame); +} diff --git a/cameraview/src/test/java/com/otaliastudios/cameraview/FrameTest.java b/cameraview/src/test/java/com/otaliastudios/cameraview/FrameTest.java new file mode 100644 index 00000000..83c8a5b5 --- /dev/null +++ b/cameraview/src/test/java/com/otaliastudios/cameraview/FrameTest.java @@ -0,0 +1,66 @@ +package com.otaliastudios.cameraview; + + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class FrameTest { + + @Test + public void testDefaults() { + Frame frame = new Frame(); + assertEquals(frame.getTime(), -1); + assertEquals(frame.getRotation(), 0); + assertNull(frame.getData()); + } + + @Test + public void testEquals() { + Frame f1 = new Frame(); + f1.set(null, 1000, 90); + Frame f2 = new Frame(); + f2.set(new byte[2], 1000, 0); + assertEquals(f1, f2); + + f2.set(new byte[2], 1001, 0); + assertNotEquals(f1, f2); + } + + @Test + public void testClear() { + Frame frame = new Frame(); + frame.set(new byte[2], 1000, 90); + frame.clear(); + + assertEquals(frame.getTime(), -1); + assertEquals(frame.getRotation(), 0); + assertNull(frame.getData()); + } + + @Test + public void testFreeze() { + Frame frame = new Frame(); + byte[] data = new byte[]{0, 1, 5, 0, 7, 3, 4, 5}; + long time = 1000; + int rotation = 90; + frame.set(data, time, rotation); + + Frame frozen = frame.freeze(); + assertArrayEquals(data, frozen.getData()); + assertEquals(time, frozen.getTime()); + assertEquals(rotation, frozen.getRotation()); + + // Mutate the first, ensure that frozen is not affected + frame.set(new byte[]{3, 2, 1}, 50, 180); + assertArrayEquals(data, frozen.getData()); + assertEquals(time, frozen.getTime()); + assertEquals(rotation, frozen.getRotation()); + } + +}