From 9ec4a7af0f45c118ef039e76eb858698037bcf41 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 28 Oct 2019 11:52:24 -0400 Subject: [PATCH] Update max video duration for MMS. --- .../securesms/mediasend/CameraXFragment.java | 15 +++++++++++++-- .../mediasend/CameraXVideoCaptureHelper.java | 13 +++++++------ .../securesms/mediasend/MediaSendViewModel.java | 4 ++++ .../thoughtcrime/securesms/video/VideoUtil.java | 12 ++++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java b/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java index aff56f8680..1b974c0139 100644 --- a/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java +++ b/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java @@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.ThemeUtil; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.SimpleTask; +import org.thoughtcrime.securesms.video.VideoUtil; import org.whispersystems.libsignal.util.guava.Optional; import java.io.FileDescriptor; @@ -237,11 +238,15 @@ public class CameraXFragment extends Fragment implements CameraFragment { camera.setCaptureMode(CameraXView.CaptureMode.MIXED); + int maxDuration = VideoUtil.getMaxVideoDurationInSeconds(requireContext(), viewModel.getMediaConstraints()); + Log.d(TAG, "Max duration: " + maxDuration + " sec"); + captureButton.setVideoCaptureListener(new CameraXVideoCaptureHelper( this, captureButton, camera, videoFileDescriptor, + maxDuration, new CameraXVideoCaptureHelper.Callback() { @Override public void onVideoRecordStarted() { @@ -266,14 +271,20 @@ public class CameraXFragment extends Fragment implements CameraFragment { Log.w(TAG, "Video capture is not supported on this device.", e); } } else { - Log.i(TAG, "Video capture not supported. API: " + Build.VERSION.SDK_INT + ", MFD: " + MemoryFileDescriptor.supported() + ", Camera: " + CameraXUtil.getLowestSupportedHardwareLevel(requireContext())); + Log.i(TAG, "Video capture not supported. " + + "API: " + Build.VERSION.SDK_INT + ", " + + "MFD: " + MemoryFileDescriptor.supported() + ", " + + "Camera: " + CameraXUtil.getLowestSupportedHardwareLevel(requireContext()) + ", " + + "MaxDuration: " + VideoUtil.getMaxVideoDurationInSeconds(requireContext(), viewModel.getMediaConstraints()) + " sec"); } viewModel.onCameraControlsInitialized(); } private boolean isVideoRecordingSupported(@NonNull Context context) { - return MediaConstraints.isVideoTranscodeAvailable() && CameraXUtil.isMixedModeSupported(context); + return MediaConstraints.isVideoTranscodeAvailable() && + CameraXUtil.isMixedModeSupported(context) && + VideoUtil.getMaxVideoDurationInSeconds(context, viewModel.getMediaConstraints()) > 0; } private void displayVideoRecordingTooltipIfNecessary(CameraButtonView captureButton) { diff --git a/src/org/thoughtcrime/securesms/mediasend/CameraXVideoCaptureHelper.java b/src/org/thoughtcrime/securesms/mediasend/CameraXVideoCaptureHelper.java index 6b7b646667..362b342800 100644 --- a/src/org/thoughtcrime/securesms/mediasend/CameraXVideoCaptureHelper.java +++ b/src/org/thoughtcrime/securesms/mediasend/CameraXVideoCaptureHelper.java @@ -40,11 +40,10 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener private final @NonNull CameraXView camera; private final @NonNull Callback callback; private final @NonNull MemoryFileDescriptor memoryFileDescriptor; + private final @NonNull ValueAnimator updateProgressAnimator; private boolean isRecording; private ValueAnimator cameraMetricsAnimator; - private final ValueAnimator updateProgressAnimator = ValueAnimator.ofFloat(0f, 1f) - .setDuration(VideoUtil.VIDEO_MAX_LENGTH_S * 1000); private final VideoCapture.OnVideoSavedListener videoSavedListener = new VideoCapture.OnVideoSavedListener() { @Override @@ -74,12 +73,14 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener @NonNull CameraButtonView captureButton, @NonNull CameraXView camera, @NonNull MemoryFileDescriptor memoryFileDescriptor, + int maxVideoDurationSec, @NonNull Callback callback) { - this.fragment = fragment; - this.camera = camera; - this.memoryFileDescriptor = memoryFileDescriptor; - this.callback = callback; + this.fragment = fragment; + this.camera = camera; + this.memoryFileDescriptor = memoryFileDescriptor; + this.callback = callback; + this.updateProgressAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(maxVideoDurationSec * 1000); updateProgressAnimator.setInterpolator(new LinearInterpolator()); updateProgressAnimator.addUpdateListener(anim -> captureButton.setProgress(anim.getAnimatedFraction())); diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java index b896ac8317..385828efc3 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java @@ -455,6 +455,10 @@ class MediaSendViewModel extends ViewModel { return FeatureFlags.VIEW_ONCE_SENDING && viewOnceState == ViewOnceState.ENABLED; } + @NonNull MediaConstraints getMediaConstraints() { + return mediaConstraints; + } + private @NonNull List getSelectedMediaOrDefault() { return selectedMedia.getValue() == null ? Collections.emptyList() : selectedMedia.getValue(); diff --git a/src/org/thoughtcrime/securesms/video/VideoUtil.java b/src/org/thoughtcrime/securesms/video/VideoUtil.java index ba3e1ae5f0..96fb912c2f 100644 --- a/src/org/thoughtcrime/securesms/video/VideoUtil.java +++ b/src/org/thoughtcrime/securesms/video/VideoUtil.java @@ -1,12 +1,15 @@ package org.thoughtcrime.securesms.video; +import android.content.Context; import android.content.res.Resources; import android.media.MediaFormat; import android.util.DisplayMetrics; import android.util.Size; +import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; +import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.util.MediaUtil; public final class VideoUtil { @@ -18,6 +21,8 @@ public final class VideoUtil { public static final int VIDEO_SHORT_WIDTH = 720; public static final int VIDEO_MAX_LENGTH_S = 30; + private static final int TOTAL_BYTES_PER_SECOND = (VIDEO_BIT_RATE / 8) + (AUDIO_BIT_RATE / 8); + @RequiresApi(21) public static final String VIDEO_MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC; public static final String AUDIO_MIME_TYPE = "audio/mp4a-latm"; @@ -33,6 +38,13 @@ public final class VideoUtil { : new Size(VIDEO_LONG_WIDTH, VIDEO_SHORT_WIDTH); } + public static int getMaxVideoDurationInSeconds(@NonNull Context context, @NonNull MediaConstraints mediaConstraints) { + int allowedSize = mediaConstraints.getCompressedVideoMaxSize(context); + int duration = (int) Math.floor((float) allowedSize / TOTAL_BYTES_PER_SECOND); + + return Math.min(duration, VIDEO_MAX_LENGTH_S); + } + @RequiresApi(21) private static Size screenSize() { DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();