Upgrade CameraX to 1.3.0-rc01

This commit is contained in:
Greyson Parrelli
2023-09-06 15:52:21 -04:00
committed by Alex Hart
parent f959543c19
commit b19aedd17c
7 changed files with 118 additions and 36 deletions

View File

@@ -3,12 +3,9 @@ package org.thoughtcrime.securesms.mediasend;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.camera.view.video.ExperimentalVideo;
import androidx.fragment.app.Fragment;
import org.thoughtcrime.securesms.R;

View File

@@ -30,10 +30,12 @@ import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.ImageProxy;
import androidx.camera.video.FallbackStrategy;
import androidx.camera.video.Quality;
import androidx.camera.video.QualitySelector;
import androidx.camera.view.CameraController;
import androidx.camera.view.LifecycleCameraController;
import androidx.camera.view.PreviewView;
import androidx.camera.view.video.ExperimentalVideo;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.core.content.ContextCompat;
@@ -71,7 +73,6 @@ import io.reactivex.rxjava3.disposables.Disposable;
* Camera captured implemented using the CameraX SDK, which uses Camera2 under the hood. Should be
* preferred whenever possible.
*/
@ExperimentalVideo
public class CameraXFragment extends LoggingFragment implements CameraFragment {
private static final String TAG = Log.tag(CameraXFragment.class);
@@ -239,7 +240,7 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment {
CameraController.OutputSize outputSize = new CameraController.OutputSize(size);
cameraController.setImageCaptureTargetSize(outputSize);
cameraController.setVideoCaptureTargetSize(new CameraController.OutputSize(VideoUtil.getVideoRecordingSize()));
cameraController.setVideoCaptureQualitySelector(QualitySelector.from(Quality.HD, FallbackStrategy.lowerQualityThan(Quality.HD)));
controlsContainer.removeAllViews();
controlsContainer.addView(LayoutInflater.from(getContext()).inflate(layout, controlsContainer, false));

View File

@@ -14,12 +14,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.camera.core.ZoomState;
import androidx.camera.video.FileDescriptorOutputOptions;
import androidx.camera.video.Recording;
import androidx.camera.video.VideoRecordEvent;
import androidx.camera.view.CameraController;
import androidx.camera.view.PreviewView;
import androidx.camera.view.video.ExperimentalVideo;
import androidx.camera.view.video.OnVideoSavedCallback;
import androidx.camera.view.video.OutputFileOptions;
import androidx.camera.view.video.OutputFileResults;
import androidx.camera.view.video.AudioConfig;
import androidx.core.util.Consumer;
import androidx.fragment.app.Fragment;
import com.bumptech.glide.util.Executors;
@@ -39,7 +40,6 @@ import java.util.Objects;
import java.util.concurrent.TimeUnit;
@RequiresApi(26)
@ExperimentalVideo
class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener {
private static final String TAG = CameraXVideoCaptureHelper.class.getName();
@@ -57,25 +57,31 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener
private ValueAnimator cameraMetricsAnimator;
private final OnVideoSavedCallback videoSavedListener = new OnVideoSavedCallback() {
@SuppressLint("RestrictedApi")
@Override
public void onVideoSaved(@NonNull OutputFileResults outputFileResults) {
try {
debouncer.clear();
cameraController.setZoomRatio(Objects.requireNonNull(cameraController.getZoomState().getValue()).getMinZoomRatio());
memoryFileDescriptor.seek(0);
callback.onVideoSaved(memoryFileDescriptor.getFileDescriptor());
} catch (IOException e) {
callback.onVideoError(e);
}
}
private @Nullable Recording activeRecording = null;
@SuppressLint("RestrictedApi")
private final Consumer<VideoRecordEvent> videoSavedListener = new Consumer<>() {
@Override
public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
debouncer.clear();
callback.onVideoError(cause);
public void accept(VideoRecordEvent videoRecordEvent) {
Log.d(TAG, "Received recording event: " + videoRecordEvent.getClass().getSimpleName());
if (videoRecordEvent instanceof VideoRecordEvent.Finalize) {
VideoRecordEvent.Finalize event = (VideoRecordEvent.Finalize) videoRecordEvent;
if (event.hasError()) {
Log.w(TAG, "Hit an error while recording! Error code: " + event.getError(), event.getCause());
debouncer.clear();
callback.onVideoError(event.getCause());
} else {
try {
debouncer.clear();
cameraController.setZoomRatio(Objects.requireNonNull(cameraController.getZoomState().getValue()).getMinZoomRatio());
memoryFileDescriptor.seek(0);
callback.onVideoSaved(memoryFileDescriptor.getFileDescriptor());
} catch (IOException e) {
callback.onVideoError(e);
}
}
}
}
};
@@ -140,9 +146,11 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener
callback.onVideoRecordStarted();
shrinkCaptureArea();
OutputFileOptions options = OutputFileOptions.builder(memoryFileDescriptor.getParcelFileDescriptor()).build();
FileDescriptorOutputOptions outputOptions = new FileDescriptorOutputOptions.Builder(memoryFileDescriptor.getParcelFileDescriptor()).build();
AudioConfig audioConfig = AudioConfig.create(true);
activeRecording = cameraController.startRecording(outputOptions, audioConfig, Executors.mainThreadExecutor(), videoSavedListener);
cameraController.startRecording(options, Executors.mainThreadExecutor(), videoSavedListener);
updateProgressAnimator.start();
debouncer.publish(this::onVideoCaptureComplete);
}
@@ -198,10 +206,19 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener
@Override
public void onVideoCaptureComplete() {
if (!canRecordAudio()) return;
if (!canRecordAudio()) {
Log.w(TAG, "Can't record audio!");
return;
}
if (activeRecording == null) {
Log.w(TAG, "No active recording!");
return;
}
Log.d(TAG, "onVideoCaptureComplete");
cameraController.stopRecording();
activeRecording.close();
activeRecording = null;
if (cameraMetricsAnimator != null && cameraMetricsAnimator.isRunning()) {
cameraMetricsAnimator.reverse();
@@ -219,6 +236,16 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener
cameraController.setZoomRatio((range * increment) + zoomState.getMinZoomRatio());
}
@Override
protected void finalize() throws Throwable {
if (activeRecording != null) {
Log.w(TAG, "Dangling recording left open in finalize()! Attempting to close.");
activeRecording.close();
}
super.finalize();
}
static MemoryFileDescriptor createFileDescriptor(@NonNull Context context) throws MemoryFileDescriptor.MemoryFileException {
return MemoryFileDescriptor.newMemoryFileDescriptor(
context,

View File

@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.mediasend.camerax
import android.content.Context
import android.os.Build
import androidx.camera.view.CameraController
import androidx.camera.view.video.ExperimentalVideo
import org.signal.core.util.asListContains
import org.thoughtcrime.securesms.mms.MediaConstraints
import org.thoughtcrime.securesms.util.FeatureFlags
@@ -12,7 +11,6 @@ import org.thoughtcrime.securesms.video.VideoUtil
/**
* Describes device capabilities
*/
@ExperimentalVideo
sealed class CameraXModePolicy {
abstract val isVideoSupported: Boolean

View File

@@ -7,7 +7,7 @@ import java.util.Set;
/**
* A set of {@link android.os.Build#MODEL} that are known to both benefit from
* {@link androidx.camera.core.ImageCapture.CaptureMode#MAX_QUALITY} and execute it quickly.
* {@link androidx.camera.core.ImageCapture.CaptureMode#CAPTURE_MODE_MAXIMIZE_QUALITY} and execute it quickly.
*
*/
public class FastCameraModels {
@@ -19,6 +19,7 @@ public class FastCameraModels {
add("Pixel 3 XL");
add("Pixel 3a");
add("Pixel 3a XL");
add("SM-S911U1");
}};
/**

View File

@@ -6,7 +6,7 @@ dependencyResolutionManagement {
libs {
version('androidx-appcompat', '1.6.1')
version('androidx-activity', '1.7.2')
version('androidx-camera', '1.2.3')
version('androidx-camera', '1.3.0-rc01')
version('androidx-fragment', '1.6.1')
version('androidx-lifecycle', '2.6.1')
version('androidx-media3', '1.1.0')

View File

@@ -144,6 +144,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="5eebeaff01d042e06dcf292abf8964ad391e4b0159f0090f16253d6045d38da0" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.annotation" name="annotation-experimental" version="1.3.1">
<artifact name="annotation-experimental-1.3.1.aar">
<sha256 value="e4d49dc3880b7b7437ea54ce71461e02897faa4e1ecc53e63ecadb1a14c20c9c" origin="Generated by Gradle"/>
</artifact>
<artifact name="annotation-experimental-1.3.1.module">
<sha256 value="9b6974a7dfe26d3c209dd63e16f8ee2461b57a091789160ca1eb492bb1bf3f84" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.annotation" name="annotation-jvm" version="1.6.0">
<artifact name="annotation-jvm-1.6.0.jar">
<sha256 value="60b10b5ef5769b79570172e015b8159405c92f034ba88b9391a977589c9deb4e" origin="Generated by Gradle"/>
@@ -289,6 +297,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="6838c8fa96f6efdac3294aa8a01c7d7ac30e2c8b634c6e08470de7aadebc5304" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-camera2" version="1.3.0-rc01">
<artifact name="camera-camera2-1.3.0-rc01.aar">
<sha256 value="a0fb0e8fca8e4f9f2d20dc55ee8021372acac4123f6d3f66365e29cfb5b70498" origin="Generated by Gradle"/>
</artifact>
<artifact name="camera-camera2-1.3.0-rc01.module">
<sha256 value="fcc7250a3edb08e1a2952fbb2dc488dbeadd1c15ada1e138ec3742d2ea99a78c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-core" version="1.2.3">
<artifact name="camera-core-1.2.3.aar">
<sha256 value="b4aeb070c0026cf15b0c24f60c72c5947c7e8ba48d392de6f5e3ecf188d5e3f7" origin="Generated by Gradle"/>
@@ -297,6 +313,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="6aed3917c7992365a6dace91ddc620f7826c1033ca558c647a8ab3cb5ebf5ae7" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-core" version="1.3.0-rc01">
<artifact name="camera-core-1.3.0-rc01.aar">
<sha256 value="b00447a46a878f77551c70de5f532d87811b92fec70934203ab3c2e51a10f4fb" origin="Generated by Gradle"/>
</artifact>
<artifact name="camera-core-1.3.0-rc01.module">
<sha256 value="b52cbeb710747adf2ea4e36eceaa9f7560ef783a000a6b23ebd3b82948ddefa1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-lifecycle" version="1.2.3">
<artifact name="camera-lifecycle-1.2.3.aar">
<sha256 value="899f45a21a81eaea2e2291bb4f4061c3afe2ea3df474cc1fedc94b6940a719cb" origin="Generated by Gradle"/>
@@ -305,6 +329,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="07084c793e9fdfd6c700559fbf736548a50d64337f0c6053bbb9a8646848c6c2" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-lifecycle" version="1.3.0-rc01">
<artifact name="camera-lifecycle-1.3.0-rc01.aar">
<sha256 value="8d3ec866d2a9013289a637eacdc64f1d3378852d76a1ba6edc6e8ab95b014246" origin="Generated by Gradle"/>
</artifact>
<artifact name="camera-lifecycle-1.3.0-rc01.module">
<sha256 value="8679ef6fec733657051dd32d26342d776427e4418e584af7aa44d66813da3e1f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-video" version="1.3.0-rc01">
<artifact name="camera-video-1.3.0-rc01.aar">
<sha256 value="b766ca808bd347341f5554296e96eed2a0412605c8f2ee02f0edcaf9ecb1dcc2" origin="Generated by Gradle"/>
</artifact>
<artifact name="camera-video-1.3.0-rc01.module">
<sha256 value="bc71cff4ba1680ec648192eb826c6a59202117eb73064424dd1c14810bb00c2f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-view" version="1.2.3">
<artifact name="camera-view-1.2.3.aar">
<sha256 value="08c0f162f75d859334e3233daaf4fcd9b80035bac8e9cd99b05681e4c68e1173" origin="Generated by Gradle"/>
@@ -313,6 +353,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="b9b191f1914ddcaae57124f01bc427ece346a8b83d122467faa3ab1bf08837e3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.camera" name="camera-view" version="1.3.0-rc01">
<artifact name="camera-view-1.3.0-rc01.aar">
<sha256 value="cc4004ed2d8b3a0666a741c870425b512bef9e4a089ddef8693e63664cf8cc91" origin="Generated by Gradle"/>
</artifact>
<artifact name="camera-view-1.3.0-rc01.module">
<sha256 value="d8017f0f6d5d0f0b09b8ffcd9e519d7cb21ffb3ba728dd6fa8dd84114d0cd734" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.cardview" name="cardview" version="1.0.0">
<artifact name="cardview-1.0.0.aar">
<sha256 value="1193c04c22a3d6b5946dae9f4e8c59d6adde6a71b6bd5d87fb99d82dda1afec7" origin="Generated by Gradle"/>
@@ -4653,6 +4701,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="042a1cd1ac976cdcfe5eb63f1d8e0b0b892c9248e15a69c8cfba495d546ea52a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.8.22">
<artifact name="kotlin-stdlib-1.8.22.jar">
<sha256 value="03a5c3965cc37051128e64e46748e394b6bd4c97fa81c6de6fc72bfd44e3421b" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.4.21">
<artifact name="kotlin-stdlib-common-1.4.21.jar">
<sha256 value="812cf197d9c4c67e1f47f95e2d72a9b600f0d1124560617bfe9850773eccbcff" origin="Generated by Gradle"/>
@@ -4693,6 +4746,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="6a44c9ecc9d7754d9e943fb1e3588c74d4a3f1785be51074f49d6c5723682a73" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.8.22">
<artifact name="kotlin-stdlib-common-1.8.22.jar">
<sha256 value="d0c2365e2437ef70f34586d50f055743f79716bcfe65e4bc7239cdd2669ef7c5" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.4.10">
<artifact name="kotlin-stdlib-jdk7-1.4.10.jar">
<sha256 value="f9566380c08722c780ce33ceee23e98ddf765ca98fabd3e2fabae7975c8d232b" origin="Generated by Gradle"/>