Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom camera engine support #1070

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import com.otaliastudios.cameraview.engine.Camera1Engine;
import com.otaliastudios.cameraview.engine.Camera2Engine;
import com.otaliastudios.cameraview.engine.CameraEngine;
import com.otaliastudios.cameraview.engine.CustomCameraEngine;
import com.otaliastudios.cameraview.engine.offset.Reference;
import com.otaliastudios.cameraview.engine.orchestrator.CameraState;
import com.otaliastudios.cameraview.filter.Filter;
Expand Down Expand Up @@ -1004,19 +1005,50 @@ public Preview getPreview() {
* if this CameraView is closed (open() was never called).
* Otherwise, it has no effect.
*
* Note: {@link Engine#CUSTOM} cannot be set with this method.
* Use {@link #setCustomEngine(CustomCameraEngine)} instead.
*
* @see Engine#CAMERA1
* @see Engine#CAMERA2
*
* @param engine desired engine
*/
public void setEngine(@NonNull Engine engine) {
if (!isClosed()) return;
if (!isClosed() || engine == Engine.CUSTOM) return;
mEngine = engine;
CameraEngine oldEngine = mCameraEngine;
doInstantiateEngine();
if (mCameraPreview != null) mCameraEngine.setPreview(mCameraPreview);

// Set again all parameters
copyCameraEngineParameters(oldEngine);
}

/**
* Allows the app to implement a custom camera engine.
* Should only be called if this CameraView is closed
* (open() was never called). Otherwise it has no effect.
*
* To use a built-in engine use {@link #setEngine(Engine)}
*
* @param engine custom engine
*/
public void setCustomEngine(@NonNull CustomCameraEngine engine) {
if (!isClosed()) return;
CameraEngine oldEngine = mCameraEngine;
mCameraEngine = engine;
mEngine = Engine.CUSTOM;
engine.setCallbacks(mCameraCallbacks);
engine.setOverlay(mOverlayLayout);
if(mCameraPreview != null) mCameraEngine.setPreview(mCameraPreview);

// Set again all parameters
copyCameraEngineParameters(oldEngine);
}

private void copyCameraEngineParameters(CameraEngine oldEngine) {
mCameraEngine.setHasFrameProcessors(!mFrameProcessors.isEmpty());
if (oldEngine == null) return;
setFacing(oldEngine.getFacing());
setFlash(oldEngine.getFlash());
setMode(oldEngine.getMode());
Expand All @@ -1041,7 +1073,6 @@ public void setEngine(@NonNull Engine engine) {
setFrameProcessingMaxHeight(oldEngine.getFrameProcessingMaxHeight());
setFrameProcessingFormat(0 /* this is very engine specific, so do not pass */);
setFrameProcessingPoolSize(oldEngine.getFrameProcessingPoolSize());
mCameraEngine.setHasFrameProcessors(!mFrameProcessors.isEmpty());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import com.otaliastudios.cameraview.CameraView;
import com.otaliastudios.cameraview.engine.CustomCameraEngine;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand All @@ -22,7 +23,13 @@ public enum Engine implements Control {
* Camera2 based engine. For API versions older than 21,
* the system falls back to {@link #CAMERA1}.
*/
CAMERA2(1);
CAMERA2(1),

/**
* Custom camera engine implemented by the app.
* See {@link CameraView#setCustomEngine(CustomCameraEngine)}.
*/
CUSTOM(2);

final static Engine DEFAULT = CAMERA1;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.otaliastudios.cameraview.engine;

import android.content.Context;
import android.graphics.PointF;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.otaliastudios.cameraview.CameraException;
import com.otaliastudios.cameraview.CameraOptions;
import com.otaliastudios.cameraview.PictureResult;
import com.otaliastudios.cameraview.VideoResult;
import com.otaliastudios.cameraview.frame.Frame;
import com.otaliastudios.cameraview.gesture.Gesture;

public class CallbackProxy implements CameraEngine.Callback {
private CameraEngine.Callback mCallbacks;

public void setCallbacks(CameraEngine.Callback callbacks) {
mCallbacks = callbacks;
}

@NonNull
@Override
public Context getContext() {
return mCallbacks.getContext();
}

@Override
public void dispatchOnCameraOpened(@NonNull CameraOptions options) {
mCallbacks.dispatchOnCameraOpened(options);
}

@Override
public void dispatchOnCameraClosed() {
mCallbacks.dispatchOnCameraClosed();
}

@Override
public void onCameraPreviewStreamSizeChanged() {
mCallbacks.onCameraPreviewStreamSizeChanged();
}

@Override
public void dispatchOnPictureShutter(boolean shouldPlaySound) {
mCallbacks.dispatchOnPictureShutter(shouldPlaySound);
}

@Override
public void dispatchOnVideoTaken(@NonNull VideoResult.Stub stub) {
mCallbacks.dispatchOnVideoTaken(stub);
}

@Override
public void dispatchOnPictureTaken(@NonNull PictureResult.Stub stub) {
mCallbacks.dispatchOnPictureTaken(stub);
}

@Override
public void dispatchOnFocusStart(@Nullable Gesture trigger, @NonNull PointF where) {
mCallbacks.dispatchOnFocusStart(trigger, where);
}

@Override
public void dispatchOnFocusEnd(@Nullable Gesture trigger, boolean success, @NonNull PointF where) {
mCallbacks.dispatchOnFocusEnd(trigger, success, where);
}

@Override
public void dispatchOnZoomChanged(float newValue, @Nullable PointF[] fingers) {
mCallbacks.dispatchOnZoomChanged(newValue, fingers);
}

@Override
public void dispatchOnExposureCorrectionChanged(float newValue, @NonNull float[] bounds, @Nullable PointF[] fingers) {
mCallbacks.dispatchOnExposureCorrectionChanged(newValue, bounds, fingers);
}

@Override
public void dispatchFrame(@NonNull Frame frame) {
mCallbacks.dispatchFrame(frame);
}

@Override
public void dispatchError(CameraException exception) {
mCallbacks.dispatchError(exception);
}

@Override
public void dispatchOnVideoRecordingStart() {
mCallbacks.dispatchOnVideoRecordingStart();
}

@Override
public void dispatchOnVideoRecordingEnd() {
mCallbacks.dispatchOnVideoRecordingEnd();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.otaliastudios.cameraview.engine;

public abstract class CustomCameraEngine extends CameraBaseEngine {
protected CustomCameraEngine() {
super(new CallbackProxy());
}

public void setCallbacks(Callback callbacks) {
((CallbackProxy) getCallback()).setCallbacks(callbacks);
}
}