mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-03-01 06:07:37 +00:00
Upgrade CameraX to 1.3.0-rc01
This commit is contained in:
committed by
Alex Hart
parent
f959543c19
commit
b19aedd17c
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user