Refined oval support

v2
Mattia Iavarone 6 years ago
parent 81a1e1e766
commit 9cf23c854e
  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.
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.
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
public void testDesiredSize() {
preview.setInputStreamSize(160, 90);
preview.setInputStreamSize(160, 90, false);
assertEquals(160, preview.getInputStreamSize().getWidth());
assertEquals(90, preview.getInputStreamSize().getHeight());
}
@ -136,7 +136,7 @@ public abstract class CameraPreviewTest extends BaseTest {
private void setDesiredAspectRatio(float desiredAspectRatio) {
preview.mCropTask.listen();
preview.setInputStreamSize((int) (10f * desiredAspectRatio), 10); // Wait...
preview.setInputStreamSize((int) (10f * desiredAspectRatio), 10, false); // Wait...
preview.mCropTask.await();
assertEquals(desiredAspectRatio, getViewAspectRatioWithScale(), 0.01f);

@ -145,19 +145,12 @@ class EglViewport extends EglElement {
return texId;
}
void drawFrame(int textureId, float[] textureMatrix) {
void drawFrame(int textureId, float[] textureMatrix, float[] textureScale) {
drawFrame(textureId, textureMatrix,
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,
* it fails miserably, not taking the scale into account.
@ -174,7 +167,7 @@ class EglViewport extends EglElement {
private void drawFrame(int textureId, float[] textureMatrix,
FloatBuffer vertexBuffer,
FloatBuffer texBuffer,
float textureScaleX, float textureScaleY) {
float[] textureScale) {
check("draw start");
// Select the program.
@ -194,7 +187,7 @@ class EglViewport extends EglElement {
check("glUniformMatrix4fv");
// Pass scale values.
GLES20.glUniform2f(muTextureScaleLocation, textureScaleX, textureScaleY);
GLES20.glUniform2fv(muTextureScaleLocation, 1, textureScale, 0);
check("glUniform2f");
// Enable the "aPosition" vertex attribute.

@ -28,14 +28,16 @@ class TextureMediaEncoder extends VideoMediaEncoder<TextureMediaEncoder.Config>
int textureId;
float scaleX;
float scaleY;
boolean scaleFlipped;
EGLContext eglContext;
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);
this.textureId = textureId;
this.scaleX = scaleX;
this.scaleY = scaleY;
this.scaleFlipped = scaleFlipped;
this.eglContext = eglContext;
}
}
@ -84,6 +86,8 @@ class TextureMediaEncoder extends VideoMediaEncoder<TextureMediaEncoder.Config>
// Nothing to do here. Waiting for the first frame.
}
private float[] mScaleXY = new float[2];
@EncoderThread
@Override
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.
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);
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.swapBuffers();
}

@ -12,7 +12,6 @@ import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.util.Log;
import android.view.SurfaceHolder;
import java.io.File;
@ -168,7 +167,8 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
mCameraCallbacks.onCameraPreviewSizeChanged();
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();
mPreviewFormat = params.getPreviewFormat();

@ -119,7 +119,8 @@ class SnapshotPictureRecorder extends PictureRecorder {
Matrix.rotateM(mTransform, 0, rotation, 0, 0, 1);
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();
// TODO: need PNG when the preview is rounded, which is an experimental thing
// In all the other cases this must be JPEG!

@ -78,6 +78,7 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren
mResult.rotation,
type, mTextureId,
scaleX, scaleY,
mPreview.mInputFlipped,
EGL14.eglGetCurrentContext()
);
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.
protected int mInputStreamWidth;
protected int mInputStreamHeight;
protected boolean mInputFlipped;
CameraPreview(Context context, ViewGroup parent, SurfaceCallback callback) {
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.
// This is called by the CameraImpl.
// 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);
mInputStreamWidth = width;
mInputStreamHeight = height;
mInputFlipped = wasFlipped;
if (mInputStreamWidth > 0 && mInputStreamHeight > 0) {
crop();
}

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

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

Loading…
Cancel
Save