Update max video duration for MMS.

This commit is contained in:
Greyson Parrelli
2019-10-28 11:52:24 -04:00
parent 70636fb4a7
commit 9ec4a7af0f
4 changed files with 36 additions and 8 deletions

View File

@@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ThemeUtil; import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask; import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.video.VideoUtil;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -237,11 +238,15 @@ public class CameraXFragment extends Fragment implements CameraFragment {
camera.setCaptureMode(CameraXView.CaptureMode.MIXED); camera.setCaptureMode(CameraXView.CaptureMode.MIXED);
int maxDuration = VideoUtil.getMaxVideoDurationInSeconds(requireContext(), viewModel.getMediaConstraints());
Log.d(TAG, "Max duration: " + maxDuration + " sec");
captureButton.setVideoCaptureListener(new CameraXVideoCaptureHelper( captureButton.setVideoCaptureListener(new CameraXVideoCaptureHelper(
this, this,
captureButton, captureButton,
camera, camera,
videoFileDescriptor, videoFileDescriptor,
maxDuration,
new CameraXVideoCaptureHelper.Callback() { new CameraXVideoCaptureHelper.Callback() {
@Override @Override
public void onVideoRecordStarted() { 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); Log.w(TAG, "Video capture is not supported on this device.", e);
} }
} else { } 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(); viewModel.onCameraControlsInitialized();
} }
private boolean isVideoRecordingSupported(@NonNull Context context) { 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) { private void displayVideoRecordingTooltipIfNecessary(CameraButtonView captureButton) {

View File

@@ -40,11 +40,10 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener
private final @NonNull CameraXView camera; private final @NonNull CameraXView camera;
private final @NonNull Callback callback; private final @NonNull Callback callback;
private final @NonNull MemoryFileDescriptor memoryFileDescriptor; private final @NonNull MemoryFileDescriptor memoryFileDescriptor;
private final @NonNull ValueAnimator updateProgressAnimator;
private boolean isRecording; private boolean isRecording;
private ValueAnimator cameraMetricsAnimator; 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() { private final VideoCapture.OnVideoSavedListener videoSavedListener = new VideoCapture.OnVideoSavedListener() {
@Override @Override
@@ -74,12 +73,14 @@ class CameraXVideoCaptureHelper implements CameraButtonView.VideoCaptureListener
@NonNull CameraButtonView captureButton, @NonNull CameraButtonView captureButton,
@NonNull CameraXView camera, @NonNull CameraXView camera,
@NonNull MemoryFileDescriptor memoryFileDescriptor, @NonNull MemoryFileDescriptor memoryFileDescriptor,
int maxVideoDurationSec,
@NonNull Callback callback) @NonNull Callback callback)
{ {
this.fragment = fragment; this.fragment = fragment;
this.camera = camera; this.camera = camera;
this.memoryFileDescriptor = memoryFileDescriptor; this.memoryFileDescriptor = memoryFileDescriptor;
this.callback = callback; this.callback = callback;
this.updateProgressAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(maxVideoDurationSec * 1000);
updateProgressAnimator.setInterpolator(new LinearInterpolator()); updateProgressAnimator.setInterpolator(new LinearInterpolator());
updateProgressAnimator.addUpdateListener(anim -> captureButton.setProgress(anim.getAnimatedFraction())); updateProgressAnimator.addUpdateListener(anim -> captureButton.setProgress(anim.getAnimatedFraction()));

View File

@@ -455,6 +455,10 @@ class MediaSendViewModel extends ViewModel {
return FeatureFlags.VIEW_ONCE_SENDING && viewOnceState == ViewOnceState.ENABLED; return FeatureFlags.VIEW_ONCE_SENDING && viewOnceState == ViewOnceState.ENABLED;
} }
@NonNull MediaConstraints getMediaConstraints() {
return mediaConstraints;
}
private @NonNull List<Media> getSelectedMediaOrDefault() { private @NonNull List<Media> getSelectedMediaOrDefault() {
return selectedMedia.getValue() == null ? Collections.emptyList() return selectedMedia.getValue() == null ? Collections.emptyList()
: selectedMedia.getValue(); : selectedMedia.getValue();

View File

@@ -1,12 +1,15 @@
package org.thoughtcrime.securesms.video; package org.thoughtcrime.securesms.video;
import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Size; import android.util.Size;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.MediaUtil;
public final class VideoUtil { 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_SHORT_WIDTH = 720;
public static final int VIDEO_MAX_LENGTH_S = 30; 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) @RequiresApi(21)
public static final String VIDEO_MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC; public static final String VIDEO_MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
public static final String AUDIO_MIME_TYPE = "audio/mp4a-latm"; 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); : 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) @RequiresApi(21)
private static Size screenSize() { private static Size screenSize() {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();