diff --git a/README.md b/README.md index 9e98a4b77..471164592 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ allprojects { } } dependencies { - implementation 'com.github.pedroSG94.RootEncoder:library:2.2.8' + implementation 'com.github.pedroSG94.RootEncoder:library:2.2.9' } ``` diff --git a/app/build.gradle b/app/build.gradle index dc90b8893..31671d8e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,5 +34,5 @@ android { dependencies { implementation project(':library') implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'com.google.android.material:material:1.9.0' + implementation 'com.google.android.material:material:1.10.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 40c7ebc6d..bc837b63f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + diff --git a/build.gradle b/build.gradle index 55b85070c..e0de01d17 100644 --- a/build.gradle +++ b/build.gradle @@ -4,8 +4,8 @@ apply plugin: 'org.jetbrains.dokka' buildscript { ext.kotlin_version = '1.9.10' ext.library_group = "com.github.pedroSG94" - ext.version_code = 228 - ext.version_name = "2.2.8" + ext.version_code = 229 + ext.version_name = "2.2.9" repositories { google() diff --git a/encoder/src/main/java/com/pedro/encoder/input/video/Camera1ApiManager.java b/encoder/src/main/java/com/pedro/encoder/input/video/Camera1ApiManager.java index f91537ad0..7a5f5516d 100644 --- a/encoder/src/main/java/com/pedro/encoder/input/video/Camera1ApiManager.java +++ b/encoder/src/main/java/com/pedro/encoder/input/video/Camera1ApiManager.java @@ -30,6 +30,8 @@ import android.view.View; import com.pedro.encoder.Frame; +import com.pedro.encoder.input.video.facedetector.FaceDetectorCallback; +import com.pedro.encoder.input.video.facedetector.UtilsKt; import java.io.IOException; import java.util.ArrayList; @@ -79,11 +81,6 @@ public class Camera1ApiManager implements Camera.PreviewCallback, Camera.FaceDet private CameraCallbacks cameraCallbacks; private final int focusAreaSize = 100; - //Face detector - public interface FaceDetectorCallback { - void onGetFaces(Camera.Face[] faces, Rect scaleSensor, int sensorOrientation); - } - private final int sensorOrientation = 0; //Value obtained from Camera.Face documentation api about bounds private final Rect faceSensorScale = new Rect(-1000, -1000, 1000, 1000); @@ -734,7 +731,7 @@ public boolean isFaceDetectionEnabled() { @Override public void onFaceDetection(Camera.Face[] faces, Camera camera) { - if (faceDetectorCallback != null) faceDetectorCallback.onGetFaces(faces, faceSensorScale, sensorOrientation); + if (faceDetectorCallback != null) faceDetectorCallback.onGetFaces(UtilsKt.mapCamera1Faces(faces), faceSensorScale, sensorOrientation); } private Rect calculateFocusArea(float x, float y, float previewWidth, float previewHeight) { diff --git a/encoder/src/main/java/com/pedro/encoder/input/video/Camera2ApiManager.java b/encoder/src/main/java/com/pedro/encoder/input/video/Camera2ApiManager.java index 3b6f7cc6c..5df691615 100644 --- a/encoder/src/main/java/com/pedro/encoder/input/video/Camera2ApiManager.java +++ b/encoder/src/main/java/com/pedro/encoder/input/video/Camera2ApiManager.java @@ -53,6 +53,9 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import com.pedro.encoder.input.video.facedetector.FaceDetectorCallback; +import com.pedro.encoder.input.video.facedetector.UtilsKt; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -81,7 +84,7 @@ public class Camera2ApiManager extends CameraDevice.StateCallback { private SurfaceView surfaceView; private TextureView textureView; private Surface surfaceEncoder; //input surfaceEncoder from videoEncoder - private CameraManager cameraManager; + private final CameraManager cameraManager; private Handler cameraHandler; private CameraCaptureSession cameraCaptureSession; private boolean prepared = false; @@ -99,11 +102,6 @@ public class Camera2ApiManager extends CameraDevice.StateCallback { private final Semaphore semaphore = new Semaphore(0); private CameraCallbacks cameraCallbacks; - //Face detector - public interface FaceDetectorCallback { - void onGetFaces(Face[] faces, Rect scaleSensor, int sensorOrientation); - } - public interface ImageCallback { void onImageAvailable(Image image); } @@ -787,8 +785,8 @@ private void prepareFaceDetectionCallback() { public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { Face[] faces = result.get(CaptureResult.STATISTICS_FACES); - if (faceDetectorCallback != null) { - faceDetectorCallback.onGetFaces(faces, faceSensorScale, sensorOrientation); + if (faceDetectorCallback != null && faces != null) { + faceDetectorCallback.onGetFaces(UtilsKt.mapCamera2Faces(faces), faceSensorScale, sensorOrientation); } } }; @@ -1008,7 +1006,7 @@ public void closeCamera(boolean resetSurface) { running = false; } - public void addImageListener(int width, int height, int format, int maxImages, ImageCallback listener) { + public void addImageListener(int width, int height, int format, int maxImages, boolean autoClose, ImageCallback listener) { boolean wasRunning = running; closeCamera(false); if (wasRunning) closeCamera(false); @@ -1020,7 +1018,7 @@ public void addImageListener(int width, int height, int format, int maxImages, I Image image = reader.acquireLatestImage(); if (image != null) { listener.onImageAvailable(image); - image.close(); + if (autoClose) image.close(); } }, new Handler(imageThread.getLooper())); if (wasRunning) { diff --git a/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/Face.kt b/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/Face.kt new file mode 100644 index 000000000..a5bc1478e --- /dev/null +++ b/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/Face.kt @@ -0,0 +1,16 @@ +package com.pedro.encoder.input.video.facedetector + +import android.graphics.Point +import android.graphics.Rect + +/** + * Created by pedro on 10/10/23. + */ +data class Face( + val id: Int?, //depend if device support it, if not supported the value could be -1 + val leftEye: Point?, //depend if device support it + val rightEye: Point?, //depend if device support it + val mouth: Point?, //depend if device support it + val rect: Rect, + val score: Int //range 1 to 100 +) diff --git a/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/FaceDetectorCallback.kt b/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/FaceDetectorCallback.kt new file mode 100644 index 000000000..ef5bc5727 --- /dev/null +++ b/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/FaceDetectorCallback.kt @@ -0,0 +1,10 @@ +package com.pedro.encoder.input.video.facedetector + +import android.graphics.Rect + +/** + * Created by pedro on 10/10/23. + */ +interface FaceDetectorCallback { + fun onGetFaces(faces: Array, scaleSensor: Rect?, sensorOrientation: Int) +} \ No newline at end of file diff --git a/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/Utils.kt b/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/Utils.kt new file mode 100644 index 000000000..62fa20e08 --- /dev/null +++ b/encoder/src/main/java/com/pedro/encoder/input/video/facedetector/Utils.kt @@ -0,0 +1,44 @@ +@file:Suppress("DEPRECATION") + +package com.pedro.encoder.input.video.facedetector + +import android.os.Build +import androidx.annotation.RequiresApi +import android.hardware.Camera.Face as Camera1Face +import android.hardware.camera2.params.Face as Camera2Face + +/** + * Created by pedro on 10/10/23. + */ + +fun Camera1Face.toFace(): Face { + return Face( + id = id, + leftEye = leftEye, + rightEye = rightEye, + mouth = mouth, + rect = rect, + score = score + ) +} + +@RequiresApi(Build.VERSION_CODES.LOLLIPOP) +fun Camera2Face.toFace(): Face { + return Face( + id = id, + leftEye = leftEyePosition, + rightEye = rightEyePosition, + mouth = mouthPosition, + rect = bounds, + score = score + ) +} + +fun mapCamera1Faces(faces: Array): Array { + return faces.map { it.toFace() }.toTypedArray() +} + +@RequiresApi(Build.VERSION_CODES.LOLLIPOP) +fun mapCamera2Faces(faces: Array): Array { + return faces.map { it.toFace() }.toTypedArray() +} \ No newline at end of file diff --git a/library/src/main/java/com/pedro/library/base/Camera1Base.java b/library/src/main/java/com/pedro/library/base/Camera1Base.java index e9c5f409b..09b1716e2 100644 --- a/library/src/main/java/com/pedro/library/base/Camera1Base.java +++ b/library/src/main/java/com/pedro/library/base/Camera1Base.java @@ -34,7 +34,6 @@ import androidx.annotation.RequiresApi; import com.pedro.encoder.EncoderErrorCallback; -import com.pedro.encoder.Frame; import com.pedro.encoder.audio.AudioEncoder; import com.pedro.encoder.audio.GetAacData; import com.pedro.encoder.input.audio.CustomAudioEffect; @@ -47,6 +46,7 @@ import com.pedro.encoder.input.video.CameraHelper; import com.pedro.encoder.input.video.CameraOpenException; import com.pedro.encoder.input.video.GetCameraData; +import com.pedro.encoder.input.video.facedetector.FaceDetectorCallback; import com.pedro.encoder.utils.CodecUtil; import com.pedro.encoder.video.FormatVideoEncoder; import com.pedro.encoder.video.GetVideoData; @@ -198,7 +198,7 @@ public void setFpsListener(FpsListener.Callback callback) { /** * @return true if success, false if fail (not supported or called before start camera) */ - public boolean enableFaceDetection(Camera1ApiManager.FaceDetectorCallback faceDetectorCallback) { + public boolean enableFaceDetection(FaceDetectorCallback faceDetectorCallback) { return cameraManager.enableFaceDetection(faceDetectorCallback); } diff --git a/library/src/main/java/com/pedro/library/base/Camera2Base.java b/library/src/main/java/com/pedro/library/base/Camera2Base.java index 2824da728..e7ac521e9 100644 --- a/library/src/main/java/com/pedro/library/base/Camera2Base.java +++ b/library/src/main/java/com/pedro/library/base/Camera2Base.java @@ -36,7 +36,6 @@ import androidx.annotation.RequiresApi; import com.pedro.encoder.EncoderErrorCallback; -import com.pedro.encoder.Frame; import com.pedro.encoder.audio.AudioEncoder; import com.pedro.encoder.audio.GetAacData; import com.pedro.encoder.input.audio.CustomAudioEffect; @@ -48,6 +47,7 @@ import com.pedro.encoder.input.video.CameraCallbacks; import com.pedro.encoder.input.video.CameraHelper; import com.pedro.encoder.input.video.CameraOpenException; +import com.pedro.encoder.input.video.facedetector.FaceDetectorCallback; import com.pedro.encoder.utils.CodecUtil; import com.pedro.encoder.video.FormatVideoEncoder; import com.pedro.encoder.video.GetVideoData; @@ -211,7 +211,7 @@ public void setFpsListener(FpsListener.Callback callback) { /** * @return true if success, false if fail (not supported or called before start camera) */ - public boolean enableFaceDetection(Camera2ApiManager.FaceDetectorCallback faceDetectorCallback) { + public boolean enableFaceDetection(FaceDetectorCallback faceDetectorCallback) { return cameraManager.enableFaceDetection(faceDetectorCallback); } @@ -1035,7 +1035,11 @@ public RecordController.Status getRecordStatus() { } public void addImageListener(int width, int height, int format, int maxImages, Camera2ApiManager.ImageCallback listener) { - cameraManager.addImageListener(width, height, format, maxImages, listener); + cameraManager.addImageListener(width, height, format, maxImages, true, listener); + } + + public void addImageListener(int width, int height, int format, int maxImages, boolean autoClose, Camera2ApiManager.ImageCallback listener) { + cameraManager.addImageListener(width, height, format, maxImages, autoClose, listener); } public void addImageListener(int format, int maxImages, Camera2ApiManager.ImageCallback listener) { diff --git a/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt b/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt index 8380d4182..eb9494ac5 100644 --- a/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt +++ b/rtsp/src/main/java/com/pedro/rtsp/rtsp/commands/CommandsManager.kt @@ -38,7 +38,7 @@ import java.util.regex.Pattern * * Class to create request to server and parse response from server. */ -class CommandsManager { +open class CommandsManager { var host: String? = null private set