Refined oval support

pull/360/head
Mattia Iavarone 6 years ago
parent fd69768ac0
commit 1a22bdc2d5
  1. 5
      MIGRATION.md
  2. 4
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraPreviewTest.java
  3. 15
      cameraview/src/main/gles/com/otaliastudios/cameraview/EglViewport.java
  4. 13
      cameraview/src/main/gles/com/otaliastudios/cameraview/TextureMediaEncoder.java
  5. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  6. 3
      cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java
  7. 1
      cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotVideoRecorder.java
  8. 4
      cameraview/src/main/views/com/otaliastudios/cameraview/CameraPreview.java
  9. 5
      cameraview/src/main/views/com/otaliastudios/cameraview/GlCameraPreview.java
  10. 4
      cameraview/src/main/views/com/otaliastudios/cameraview/TextureCameraPreview.java

@ -59,4 +59,7 @@
- UI Changes in the demo app, changed controls appearance, added some missing controls. - UI Changes in the demo app, changed controls appearance, added some missing controls.
added all information from the VideoResult in the VideoPreviewActivity, same for pictures added all information from the VideoResult in the VideoPreviewActivity, same for pictures
- BitmapCallback result is now @Nullable ! This will happen if we encounter an OutOfMemoryError during decoding. - BitmapCallback result is now @Nullable ! This will happen if we encounter an OutOfMemoryError during decoding.
You should consider passing a maxWidth and maxHeight instead of loading the full image. You should consider passing a maxWidth and maxHeight instead of loading the full image.
- TODO: add Shape control: RECT and OVAL. Pass this shape around, to the preview and whoever needs it
- TODO: add setPreviewSize API (think about it)
- TODO: fix video recording rotation: with front camera, it does not work.

@ -86,7 +86,7 @@ public abstract class CameraPreviewTest extends BaseTest {
@Test @Test
public void testDesiredSize() { public void testDesiredSize() {
preview.setInputStreamSize(160, 90); preview.setInputStreamSize(160, 90, false);
assertEquals(160, preview.getInputStreamSize().getWidth()); assertEquals(160, preview.getInputStreamSize().getWidth());
assertEquals(90, preview.getInputStreamSize().getHeight()); assertEquals(90, preview.getInputStreamSize().getHeight());
} }
@ -136,7 +136,7 @@ public abstract class CameraPreviewTest extends BaseTest {
private void setDesiredAspectRatio(float desiredAspectRatio) { private void setDesiredAspectRatio(float desiredAspectRatio) {
preview.mCropTask.listen(); preview.mCropTask.listen();
preview.setInputStreamSize((int) (10f * desiredAspectRatio), 10); // Wait... preview.setInputStreamSize((int) (10f * desiredAspectRatio), 10, false); // Wait...
preview.mCropTask.await(); preview.mCropTask.await();
assertEquals(desiredAspectRatio, getViewAspectRatioWithScale(), 0.01f); assertEquals(desiredAspectRatio, getViewAspectRatioWithScale(), 0.01f);

@ -145,19 +145,12 @@ class EglViewport extends EglElement {
return texId; return texId;
} }
void drawFrame(int textureId, float[] textureMatrix) { void drawFrame(int textureId, float[] textureMatrix, float[] textureScale) {
drawFrame(textureId, textureMatrix, drawFrame(textureId, textureMatrix,
mVertexCoordinatesArray, mVertexCoordinatesArray,
mTextureCoordinatesArray, 1F, 1F); mTextureCoordinatesArray, textureScale);
} }
void drawFrame(int textureId, float[] textureMatrix, float textureScaleX, float textureScaleY) {
drawFrame(textureId, textureMatrix,
mVertexCoordinatesArray,
mTextureCoordinatesArray, textureScaleX, textureScaleY);
}
private static final FloatBuffer TEMP = floatBuffer(new float[] { 1.0F, 1.0F });
/** /**
* The issue with the CIRCLE shader is that if the textureMatrix has a scale value, * The issue with the CIRCLE shader is that if the textureMatrix has a scale value,
* it fails miserably, not taking the scale into account. * it fails miserably, not taking the scale into account.
@ -174,7 +167,7 @@ class EglViewport extends EglElement {
private void drawFrame(int textureId, float[] textureMatrix, private void drawFrame(int textureId, float[] textureMatrix,
FloatBuffer vertexBuffer, FloatBuffer vertexBuffer,
FloatBuffer texBuffer, FloatBuffer texBuffer,
float textureScaleX, float textureScaleY) { float[] textureScale) {
check("draw start"); check("draw start");
// Select the program. // Select the program.
@ -194,7 +187,7 @@ class EglViewport extends EglElement {
check("glUniformMatrix4fv"); check("glUniformMatrix4fv");
// Pass scale values. // Pass scale values.
GLES20.glUniform2f(muTextureScaleLocation, textureScaleX, textureScaleY); GLES20.glUniform2fv(muTextureScaleLocation, 1, textureScale, 0);
check("glUniform2f"); check("glUniform2f");
// Enable the "aPosition" vertex attribute. // Enable the "aPosition" vertex attribute.

@ -28,14 +28,16 @@ class TextureMediaEncoder extends VideoMediaEncoder<TextureMediaEncoder.Config>
int textureId; int textureId;
float scaleX; float scaleX;
float scaleY; float scaleY;
boolean scaleFlipped;
EGLContext eglContext; EGLContext eglContext;
Config(int width, int height, int bitRate, int frameRate, int rotation, String mimeType, Config(int width, int height, int bitRate, int frameRate, int rotation, String mimeType,
int textureId, float scaleX, float scaleY, EGLContext eglContext) { int textureId, float scaleX, float scaleY, boolean scaleFlipped, EGLContext eglContext) {
super(width, height, bitRate, frameRate, rotation, mimeType); super(width, height, bitRate, frameRate, rotation, mimeType);
this.textureId = textureId; this.textureId = textureId;
this.scaleX = scaleX; this.scaleX = scaleX;
this.scaleY = scaleY; this.scaleY = scaleY;
this.scaleFlipped = scaleFlipped;
this.eglContext = eglContext; this.eglContext = eglContext;
} }
} }
@ -84,6 +86,8 @@ class TextureMediaEncoder extends VideoMediaEncoder<TextureMediaEncoder.Config>
// Nothing to do here. Waiting for the first frame. // Nothing to do here. Waiting for the first frame.
} }
private float[] mScaleXY = new float[2];
@EncoderThread @EncoderThread
@Override @Override
void notify(String event, Object data) { void notify(String event, Object data) {
@ -119,11 +123,14 @@ class TextureMediaEncoder extends VideoMediaEncoder<TextureMediaEncoder.Config>
// translate to origin, rotate, then back to where we were. // translate to origin, rotate, then back to where we were.
Matrix.translateM(transform, 0, 0.5F, 0.5F, 0); Matrix.translateM(transform, 0, 0.5F, 0.5F, 0);
Matrix.rotateM(transform, 0, mConfig.rotation, 0, 0, 1); Matrix.rotateM(transform, 0, mConfig.rotation /* VIEW-OUTPUT */, 0, 0, 1);
Matrix.translateM(transform, 0, -0.5F, -0.5F, 0); Matrix.translateM(transform, 0, -0.5F, -0.5F, 0);
drain(false); drain(false);
mViewport.drawFrame(mConfig.textureId, transform, scaleX, scaleY); boolean flip = mConfig.scaleFlipped;// mConfig.rotation % 180 != 0;
mScaleXY[0] = flip ? scaleY : scaleX;
mScaleXY[1] = flip ? scaleX : scaleY;
mViewport.drawFrame(mConfig.textureId, transform, mScaleXY);
mWindow.setPresentationTime(timestamp); mWindow.setPresentationTime(timestamp);
mWindow.swapBuffers(); mWindow.swapBuffers();
} }

@ -12,7 +12,6 @@ import android.os.Build;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread; import android.support.annotation.WorkerThread;
import android.util.Log;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import java.io.File; import java.io.File;
@ -168,7 +167,8 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
mCameraCallbacks.onCameraPreviewSizeChanged(); mCameraCallbacks.onCameraPreviewSizeChanged();
Size previewSize = getPreviewSize(REF_VIEW); Size previewSize = getPreviewSize(REF_VIEW);
mPreview.setInputStreamSize(previewSize.getWidth(), previewSize.getHeight()); boolean wasFlipped = flip(REF_SENSOR, REF_VIEW);
mPreview.setInputStreamSize(previewSize.getWidth(), previewSize.getHeight(), wasFlipped);
Camera.Parameters params = mCamera.getParameters(); Camera.Parameters params = mCamera.getParameters();
mPreviewFormat = params.getPreviewFormat(); mPreviewFormat = params.getPreviewFormat();

@ -119,7 +119,8 @@ class SnapshotPictureRecorder extends PictureRecorder {
Matrix.rotateM(mTransform, 0, rotation, 0, 0, 1); Matrix.rotateM(mTransform, 0, rotation, 0, 0, 1);
Matrix.translateM(mTransform, 0, -0.5F, -0.5F, 0); Matrix.translateM(mTransform, 0, -0.5F, -0.5F, 0);
viewport.drawFrame(mTextureId, mTransform, realScaleX, realScaleY); float[] scaleXY = new float[] { realScaleX, realScaleY };
viewport.drawFrame(mTextureId, mTransform, scaleXY);
// don't - surface.swapBuffers(); // don't - surface.swapBuffers();
// TODO: need PNG when the preview is rounded, which is an experimental thing // TODO: need PNG when the preview is rounded, which is an experimental thing
// In all the other cases this must be JPEG! // In all the other cases this must be JPEG!

@ -78,6 +78,7 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren
mResult.rotation, mResult.rotation,
type, mTextureId, type, mTextureId,
scaleX, scaleY, scaleX, scaleY,
mPreview.mInputFlipped,
EGL14.eglGetCurrentContext() EGL14.eglGetCurrentContext()
); );
TextureMediaEncoder videoEncoder = new TextureMediaEncoder(config); TextureMediaEncoder videoEncoder = new TextureMediaEncoder(config);

@ -31,6 +31,7 @@ abstract class CameraPreview<T extends View, Output> {
// These are the preview stream dimensions, in REF_VIEW. // These are the preview stream dimensions, in REF_VIEW.
protected int mInputStreamWidth; protected int mInputStreamWidth;
protected int mInputStreamHeight; protected int mInputStreamHeight;
protected boolean mInputFlipped;
CameraPreview(Context context, ViewGroup parent, SurfaceCallback callback) { CameraPreview(Context context, ViewGroup parent, SurfaceCallback callback) {
mView = onCreateView(context, parent); mView = onCreateView(context, parent);
@ -52,10 +53,11 @@ abstract class CameraPreview<T extends View, Output> {
// As far as I can see, these are the actual preview dimensions, as set in CameraParameters. // As far as I can see, these are the actual preview dimensions, as set in CameraParameters.
// This is called by the CameraImpl. // This is called by the CameraImpl.
// These must be alredy rotated, if needed, to be consistent with surface/view sizes. // These must be alredy rotated, if needed, to be consistent with surface/view sizes.
void setInputStreamSize(int width, int height) { void setInputStreamSize(int width, int height, boolean wasFlipped) {
LOG.i("setInputStreamSize:", "desiredW=", width, "desiredH=", height); LOG.i("setInputStreamSize:", "desiredW=", width, "desiredH=", height);
mInputStreamWidth = width; mInputStreamWidth = width;
mInputStreamHeight = height; mInputStreamHeight = height;
mInputFlipped = wasFlipped;
if (mInputStreamWidth > 0 && mInputStreamHeight > 0) { if (mInputStreamWidth > 0 && mInputStreamHeight > 0) {
crop(); crop();
} }

@ -69,6 +69,7 @@ class GlCameraPreview extends CameraPreview<GLSurfaceView, SurfaceTexture> imple
private Set<RendererFrameCallback> mRendererFrameCallbacks = Collections.synchronizedSet(new HashSet<RendererFrameCallback>()); private Set<RendererFrameCallback> mRendererFrameCallbacks = Collections.synchronizedSet(new HashSet<RendererFrameCallback>());
/* for tests */ float mScaleX = 1F; /* for tests */ float mScaleX = 1F;
/* for tests */ float mScaleY = 1F; /* for tests */ float mScaleY = 1F;
private float[] mScaleXY = new float[] { mScaleX, mScaleY };
GlCameraPreview(Context context, ViewGroup parent, SurfaceCallback callback) { GlCameraPreview(Context context, ViewGroup parent, SurfaceCallback callback) {
super(context, parent, callback); super(context, parent, callback);
@ -227,7 +228,9 @@ class GlCameraPreview extends CameraPreview<GLSurfaceView, SurfaceTexture> imple
Matrix.translateM(mTransformMatrix, 0, translX, translY, 0); Matrix.translateM(mTransformMatrix, 0, translX, translY, 0);
Matrix.scaleM(mTransformMatrix, 0, mScaleX, mScaleY, 1); Matrix.scaleM(mTransformMatrix, 0, mScaleX, mScaleY, 1);
} }
mOutputViewport.drawFrame(mOutputTextureId, mTransformMatrix, mScaleX, mScaleY); mScaleXY[0] = mInputFlipped ? mScaleY : mScaleX;
mScaleXY[1] = mInputFlipped ? mScaleX : mScaleY;
mOutputViewport.drawFrame(mOutputTextureId, mTransformMatrix, mScaleXY);
for (RendererFrameCallback callback : mRendererFrameCallbacks) { for (RendererFrameCallback callback : mRendererFrameCallbacks) {
callback.onRendererFrame(mInputSurfaceTexture, mScaleX, mScaleY); callback.onRendererFrame(mInputSurfaceTexture, mScaleX, mScaleY);
} }

@ -58,8 +58,8 @@ class TextureCameraPreview extends CameraPreview<TextureView, SurfaceTexture> {
@TargetApi(15) @TargetApi(15)
@Override @Override
void setInputStreamSize(int width, int height) { void setInputStreamSize(int width, int height, boolean wasFlipped) {
super.setInputStreamSize(width, height); super.setInputStreamSize(width, height, wasFlipped);
if (getView().getSurfaceTexture() != null) { if (getView().getSurfaceTexture() != null) {
getView().getSurfaceTexture().setDefaultBufferSize(width, height); getView().getSurfaceTexture().setDefaultBufferSize(width, height);
} }

Loading…
Cancel
Save