Fix tests, improve performance

pull/502/head
Mattia Iavarone 6 years ago
parent e83206be7a
commit bff7bc4320
  1. 13
      cameraview/src/main/java/com/otaliastudios/cameraview/overlay/Overlay.java
  2. 27
      cameraview/src/main/java/com/otaliastudios/cameraview/overlay/OverlayLayout.java
  3. 7
      cameraview/src/main/java/com/otaliastudios/cameraview/picture/SnapshotGlPictureRecorder.java
  4. 32
      cameraview/src/main/java/com/otaliastudios/cameraview/preview/CameraPreview.java
  5. 3
      cameraview/src/main/java/com/otaliastudios/cameraview/preview/GlCameraPreview.java
  6. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/preview/SurfaceCameraPreview.java
  7. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/preview/TextureCameraPreview.java
  8. 19
      cameraview/src/main/java/com/otaliastudios/cameraview/video/SnapshotVideoRecorder.java
  9. 18
      cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/TextureMediaEncoder.java
  10. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/VideoMediaEncoder.java

@ -15,8 +15,19 @@ public interface Overlay {
/**
* Called for this overlay to draw itself on the specified target and canvas.
*
* @param target target
* @param canvas target canvas
*/
void draw(@NonNull Target target, @NonNull Canvas canvas);
void drawOn(@NonNull Target target, @NonNull Canvas canvas);
/**
* Called to understand if this overlay would like to draw onto the given
* target or not. If true is returned, {@link #drawOn(Target, Canvas)} can be
* called at a future time.
*
* @param target the target
* @return true to draw on it
*/
boolean drawsOn(@NonNull Target target);
}

@ -81,7 +81,18 @@ public class OverlayLayout extends FrameLayout implements Overlay {
@Override
public void draw(Canvas canvas) {
LOG.i("normal draw called.");
draw(Target.PREVIEW, canvas);
if (drawsOn(Target.PREVIEW)) {
drawOn(Target.PREVIEW, canvas);
}
}
@Override
public boolean drawsOn(@NonNull Target target) {
for (int i = 0; i < getChildCount(); i++) {
LayoutParams params = (LayoutParams) getChildAt(i).getLayoutParams();
if (params.drawsOn(target)) return true;
}
return false;
}
/**
@ -96,7 +107,7 @@ public class OverlayLayout extends FrameLayout implements Overlay {
* @param canvas the canvas
*/
@Override
public void draw(@NonNull Target target, @NonNull Canvas canvas) {
public void drawOn(@NonNull Target target, @NonNull Canvas canvas) {
synchronized (this) {
currentTarget = target;
switch (target) {
@ -134,11 +145,7 @@ public class OverlayLayout extends FrameLayout implements Overlay {
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
LayoutParams params = (LayoutParams) child.getLayoutParams();
boolean draw = ((currentTarget == Target.PREVIEW && params.drawOnPreview)
|| (currentTarget == Target.VIDEO_SNAPSHOT && params.drawOnVideoSnapshot)
|| (currentTarget == Target.PICTURE_SNAPSHOT && params.drawOnPictureSnapshot)
);
if (draw) {
if (params.drawsOn(currentTarget)) {
LOG.v("Performing drawing for view:", child.getClass().getSimpleName(),
"target:", currentTarget,
"params:", params);
@ -173,6 +180,12 @@ public class OverlayLayout extends FrameLayout implements Overlay {
}
}
private boolean drawsOn(@NonNull Target target) {
return ((target == Target.PREVIEW && drawOnPreview)
|| (target == Target.VIDEO_SNAPSHOT && drawOnVideoSnapshot)
|| (target == Target.PICTURE_SNAPSHOT && drawOnPictureSnapshot));
}
@NonNull
@Override
public String toString() {

@ -35,9 +35,6 @@ import androidx.annotation.Nullable;
import android.view.Surface;
import java.util.ArrayList;
import java.util.List;
public class SnapshotGlPictureRecorder extends PictureRecorder {
private static final String TAG = SnapshotGlPictureRecorder.class.getSimpleName();
@ -61,7 +58,7 @@ public class SnapshotGlPictureRecorder extends PictureRecorder {
mPreview = preview;
mOutputRatio = outputRatio;
mOverlay = overlay;
mHasOverlay = overlay != null;
mHasOverlay = overlay != null && overlay.drawsOn(Overlay.Target.PICTURE_SNAPSHOT);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@ -168,7 +165,7 @@ public class SnapshotGlPictureRecorder extends PictureRecorder {
try {
final Canvas surfaceCanvas = mOverlaySurface.lockCanvas(null);
surfaceCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mOverlay.draw(Overlay.Target.PICTURE_SNAPSHOT, surfaceCanvas);
mOverlay.drawOn(Overlay.Target.PICTURE_SNAPSHOT, surfaceCanvas);
mOverlaySurface.unlockCanvasAndPost(surfaceCanvas);
} catch (Surface.OutOfResourcesException e) {
LOG.w("Got Surface.OutOfResourcesException while drawing picture overlays", e);

@ -1,14 +1,21 @@
package com.otaliastudios.cameraview.preview;
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import com.google.android.gms.tasks.TaskCompletionSource;
import com.google.android.gms.tasks.Tasks;
import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.engine.CameraEngine;
import com.otaliastudios.cameraview.internal.utils.Op;
@ -240,7 +247,32 @@ public abstract class CameraPreview<T extends View, Output> {
* Called by the hosting {@link com.otaliastudios.cameraview.CameraView},
* this is a lifecycle event.
*/
@CallSuper
public void onDestroy() {
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
onDestroyView();
} else {
// Do this on the UI thread and wait.
Handler ui = new Handler(Looper.getMainLooper());
final TaskCompletionSource<Void> task = new TaskCompletionSource<>();
ui.post(new Runnable() {
@Override
public void run() {
onDestroyView();
task.setResult(null);
}
});
try { Tasks.await(task.getTask()); } catch (Exception ignore) {}
}
}
/**
* At this point we undo the work that was done during {@link #onCreateView(Context, ViewGroup)},
* which basically means removing the root view from the hierarchy.
*/
@SuppressWarnings("WeakerAccess")
@UiThread
protected void onDestroyView() {
View root = getRootView();
ViewParent parent = root.getParent();
if (parent instanceof ViewGroup) {

@ -5,7 +5,6 @@ import android.graphics.SurfaceTexture;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import android.view.LayoutInflater;
@ -91,7 +90,7 @@ public class GlCameraPreview extends CameraPreview<GLSurfaceView, SurfaceTexture
mDispatched = false;
}
});
parent.addView(root, 1);
parent.addView(root, 0);
mRootView = root;
return glView;
}

@ -34,7 +34,7 @@ public class SurfaceCameraPreview extends CameraPreview<SurfaceView, SurfaceHold
@Override
protected SurfaceView onCreateView(@NonNull Context context, @NonNull ViewGroup parent) {
View root = LayoutInflater.from(context).inflate(R.layout.cameraview_surface_view, parent, false);
parent.addView(root, 1);
parent.addView(root, 0);
SurfaceView surfaceView = root.findViewById(R.id.surface_view);
final SurfaceHolder holder = surfaceView.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

@ -38,7 +38,7 @@ public class TextureCameraPreview extends CameraPreview<TextureView, SurfaceText
@Override
protected TextureView onCreateView(@NonNull Context context, @NonNull ViewGroup parent) {
View root = LayoutInflater.from(context).inflate(R.layout.cameraview_texture_view, parent, false);
parent.addView(root, 1);
parent.addView(root, 0);
TextureView texture = root.findViewById(R.id.texture_view);
texture.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {

@ -8,15 +8,11 @@ import android.opengl.EGL14;
import android.os.Build;
import android.view.Surface;
import java.util.ArrayList;
import java.util.List;
import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.overlay.Overlay;
import com.otaliastudios.cameraview.VideoResult;
import com.otaliastudios.cameraview.controls.Audio;
import com.otaliastudios.cameraview.engine.CameraEngine;
import com.otaliastudios.cameraview.engine.offset.Reference;
import com.otaliastudios.cameraview.internal.egl.EglViewport;
import com.otaliastudios.cameraview.preview.GlCameraPreview;
import com.otaliastudios.cameraview.preview.RendererFrameCallback;
@ -49,9 +45,7 @@ public class SnapshotVideoRecorder extends VideoRecorder implements RendererFram
private static final int STATE_NOT_RECORDING = 1;
private MediaEncoderEngine mEncoderEngine;
private CameraEngine mEngine;
private GlCameraPreview mPreview;
private boolean mFlipped;
private int mCurrentState = STATE_NOT_RECORDING;
private int mDesiredState = STATE_NOT_RECORDING;
@ -70,16 +64,14 @@ public class SnapshotVideoRecorder extends VideoRecorder implements RendererFram
int overlayRotation) {
super(engine);
mPreview = preview;
mEngine = engine;
mOverlay = overlay;
mHasOverlay = overlay != null;
mHasOverlay = overlay != null && overlay.drawsOn(Overlay.Target.VIDEO_SNAPSHOT);
mOverlayRotation = overlayRotation;
}
@Override
protected void onStart() {
mPreview.addRendererFrameCallback(this);
mFlipped = mEngine.getAngles().flip(Reference.SENSOR, Reference.VIEW);
mDesiredState = STATE_RECORDING;
dispatchVideoRecordingStart();
}
@ -131,11 +123,10 @@ public class SnapshotVideoRecorder extends VideoRecorder implements RendererFram
mResult.videoFrameRate,
mResult.rotation,
type, mTextureId,
mHasOverlay ? mOverlayTextureId : TextureMediaEncoder.NO_TEXTURE,
mOverlayRotation,
scaleX, scaleY,
mFlipped,
EGL14.eglGetCurrentContext()
EGL14.eglGetCurrentContext(),
mHasOverlay ? mOverlayTextureId : TextureMediaEncoder.NO_TEXTURE,
mOverlayRotation
);
TextureMediaEncoder videoEncoder = new TextureMediaEncoder(config);
@ -165,7 +156,7 @@ public class SnapshotVideoRecorder extends VideoRecorder implements RendererFram
try {
final Canvas surfaceCanvas = mOverlaySurface.lockCanvas(null);
surfaceCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mOverlay.draw(Overlay.Target.VIDEO_SNAPSHOT, surfaceCanvas);
mOverlay.drawOn(Overlay.Target.VIDEO_SNAPSHOT, surfaceCanvas);
mOverlaySurface.unlockCanvasAndPost(surfaceCanvas);
} catch (Surface.OutOfResourcesException e) {
LOG.w("Got Surface.OutOfResourcesException while drawing video overlays", e);

@ -31,25 +31,27 @@ public class TextureMediaEncoder extends VideoMediaEncoder<TextureMediaEncoder.C
int overlayTextureId;
float scaleX;
float scaleY;
boolean scaleFlipped;
EGLContext eglContext;
int transformRotation;
int overlayTransformRotation;
public Config(int width, int height, int bitRate, int frameRate, int rotation, String mimeType,
int textureId, int overlayTextureId, int overlayTransformRotation,
float scaleX, float scaleY, boolean scaleFlipped, EGLContext eglContext) {
public Config(int width, int height,
int bitRate, int frameRate,
int rotation, @NonNull String mimeType,
int textureId,
float scaleX, float scaleY,
@NonNull EGLContext eglContext,
int overlayTextureId, int overlayRotation) {
// We rotate the texture using transformRotation. Pass rotation=0 to super so that
// no rotation metadata is written into the output file.
super(width, height, bitRate, frameRate, 0, mimeType);
this.transformRotation = rotation;
this.textureId = textureId;
this.overlayTextureId = overlayTextureId;
this.overlayTransformRotation = overlayTransformRotation;
this.scaleX = scaleX;
this.scaleY = scaleY;
this.scaleFlipped = scaleFlipped;
this.eglContext = eglContext;
this.overlayTextureId = overlayTextureId;
this.overlayTransformRotation = overlayRotation;
}
}
@ -149,8 +151,6 @@ public class TextureMediaEncoder extends VideoMediaEncoder<TextureMediaEncoder.C
LOG.v("onEvent", "frameNum:", thisFrameNum, "realFrameNum:", mFrameNum, "calling drainOutput.");
drainOutput(false);
// Future note: passing scale values to the viewport? They are scaleX and scaleY,
// but flipped based on the mConfig.scaleFlipped boolean.
LOG.v("onEvent", "frameNum:", thisFrameNum, "realFrameNum:", mFrameNum, "calling drawFrame.");
mViewport.drawFrame(mConfig.textureId, transform);
if (hasOverlay) {

@ -42,7 +42,7 @@ abstract class VideoMediaEncoder<C extends VideoMediaEncoder.Config> extends Med
int rotation;
String mimeType;
Config(int width, int height, int bitRate, int frameRate, int rotation, String mimeType) {
Config(int width, int height, int bitRate, int frameRate, int rotation, @NonNull String mimeType) {
this.width = width;
this.height = height;
this.bitRate = bitRate;

Loading…
Cancel
Save