mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-07-09 07:24:06 +01:00
Calculate video encoding settings based on trimmed duration.
This commit is contained in:
committed by
Greyson Parrelli
parent
a3438d3345
commit
6fc9055221
@@ -249,10 +249,12 @@ public final class AttachmentCompressionJob extends BaseJob {
|
||||
throw new UndeliverableMessageException("Cannot get media data source for attachment.");
|
||||
}
|
||||
|
||||
allowSkipOnFailure = !transformProperties.getVideoEdited();
|
||||
TranscoderOptions options = null;
|
||||
if (transformProperties.videoTrim) {
|
||||
options = new TranscoderOptions(transformProperties.videoTrimStartTimeUs, transformProperties.videoTrimEndTimeUs);
|
||||
if (transformProperties != null) {
|
||||
allowSkipOnFailure = !transformProperties.getVideoEdited();
|
||||
if (transformProperties.videoTrim) {
|
||||
options = new TranscoderOptions(transformProperties.videoTrimStartTimeUs, transformProperties.videoTrimEndTimeUs);
|
||||
}
|
||||
}
|
||||
|
||||
if (FeatureFlags.useStreamingVideoMuxer()) {
|
||||
|
||||
@@ -98,7 +98,7 @@ public final class VideoEditorHud extends LinearLayout {
|
||||
long size = tryGetUriSize(getContext(), uri, Long.MAX_VALUE);
|
||||
|
||||
if (size > maxSendSize) {
|
||||
videoTimeLine.setTimeLimit(VideoUtil.getMaxVideoUploadDurationInSeconds(), TimeUnit.SECONDS);
|
||||
videoTimeLine.setTimeLimit(videoBitRateCalculator.getMaxVideoUploadDurationInSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
videoTimeLine.setOnRangeChangeListener(new VideoThumbnailsRangeSelectorView.OnRangeChangeListener() {
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RequiresApi(26)
|
||||
public final class InMemoryTranscoder implements Closeable {
|
||||
@@ -63,8 +64,13 @@ public final class InMemoryTranscoder implements Closeable {
|
||||
throw new VideoSourceException("Unable to read datasource", e);
|
||||
}
|
||||
|
||||
if (options != null && options.endTimeUs != 0) {
|
||||
this.duration = TimeUnit.MICROSECONDS.toMillis(options.endTimeUs - options.startTimeUs);
|
||||
} else {
|
||||
this.duration = getDuration(mediaMetadataRetriever);
|
||||
}
|
||||
|
||||
this.inSize = dataSource.getSize();
|
||||
this.duration = getDuration(mediaMetadataRetriever);
|
||||
this.inputBitRate = VideoBitRateCalculator.bitRate(inSize, duration);
|
||||
this.targetQuality = new VideoBitRateCalculator(upperSizeLimit).getTargetQuality(duration, inputBitRate);
|
||||
this.upperSizeLimit = upperSizeLimit;
|
||||
|
||||
@@ -29,10 +29,6 @@ public final class VideoUtil {
|
||||
return Math.min(duration, VideoConstants.VIDEO_MAX_RECORD_LENGTH_S);
|
||||
}
|
||||
|
||||
public static int getMaxVideoUploadDurationInSeconds() {
|
||||
return Math.toIntExact(TimeUnit.MINUTES.toSeconds(10));
|
||||
}
|
||||
|
||||
private static Size screenSize() {
|
||||
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
|
||||
return new Size(metrics.widthPixels, metrics.heightPixels);
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RequiresApi(26)
|
||||
public final class StreamingTranscoder {
|
||||
@@ -58,8 +59,13 @@ public final class StreamingTranscoder {
|
||||
throw new VideoSourceException("Unable to read datasource", e);
|
||||
}
|
||||
|
||||
if (options != null && options.endTimeUs != 0) {
|
||||
this.duration = TimeUnit.MICROSECONDS.toMillis(options.endTimeUs - options.startTimeUs);
|
||||
} else {
|
||||
this.duration = getDuration(mediaMetadataRetriever);
|
||||
}
|
||||
|
||||
this.inSize = dataSource.getSize();
|
||||
this.duration = getDuration(mediaMetadataRetriever);
|
||||
this.inputBitRate = VideoBitRateCalculator.bitRate(inSize, duration);
|
||||
this.targetQuality = new VideoBitRateCalculator(upperSizeLimit).getTargetQuality(duration, inputBitRate);
|
||||
this.upperSizeLimit = upperSizeLimit;
|
||||
|
||||
+7
-8
@@ -7,11 +7,6 @@ import org.thoughtcrime.securesms.video.videoconverter.utils.VideoConstants;
|
||||
*/
|
||||
public final class VideoBitRateCalculator {
|
||||
|
||||
private static final int MAXIMUM_TARGET_VIDEO_BITRATE = VideoConstants.VIDEO_BIT_RATE;
|
||||
private static final int LOW_RES_TARGET_VIDEO_BITRATE = 1_750_000;
|
||||
private static final int MINIMUM_TARGET_VIDEO_BITRATE = 500_000;
|
||||
private static final int LOW_RES_OUTPUT_FORMAT = 480;
|
||||
|
||||
private final long upperFileSizeLimitWithMargin;
|
||||
|
||||
public VideoBitRateCalculator(long upperFileSizeLimit) {
|
||||
@@ -22,13 +17,13 @@ public final class VideoBitRateCalculator {
|
||||
* Gets the output quality of a video of the given {@param duration}.
|
||||
*/
|
||||
public TranscodingQuality getTargetQuality(long duration, int inputTotalBitRate) {
|
||||
int maxVideoBitRate = Math.min(MAXIMUM_TARGET_VIDEO_BITRATE, inputTotalBitRate - VideoConstants.AUDIO_BIT_RATE);
|
||||
int minVideoBitRate = Math.min(MINIMUM_TARGET_VIDEO_BITRATE, maxVideoBitRate);
|
||||
int maxVideoBitRate = Math.min(VideoConstants.VIDEO_TARGET_BIT_RATE, inputTotalBitRate - VideoConstants.AUDIO_BIT_RATE);
|
||||
int minVideoBitRate = Math.min(VideoConstants.VIDEO_MINIMUM_TARGET_BIT_RATE, maxVideoBitRate);
|
||||
|
||||
int targetVideoBitRate = Math.max(minVideoBitRate, Math.min(getTargetVideoBitRate(upperFileSizeLimitWithMargin, duration), maxVideoBitRate));
|
||||
int bitRateRange = maxVideoBitRate - minVideoBitRate;
|
||||
double quality = bitRateRange == 0 ? 1 : (targetVideoBitRate - minVideoBitRate) / (double) bitRateRange;
|
||||
int outputResolution = targetVideoBitRate < LOW_RES_TARGET_VIDEO_BITRATE ? LOW_RES_OUTPUT_FORMAT : VideoConstants.VIDEO_SHORT_EDGE;
|
||||
int outputResolution = targetVideoBitRate < VideoConstants.LOW_RES_TARGET_VIDEO_BITRATE ? VideoConstants.LOW_RES_OUTPUT_FORMAT : VideoConstants.VIDEO_SHORT_EDGE;
|
||||
|
||||
return new TranscodingQuality(targetVideoBitRate, VideoConstants.AUDIO_BIT_RATE, Math.max(0, Math.min(quality, 1)), duration, outputResolution);
|
||||
}
|
||||
@@ -47,4 +42,8 @@ public final class VideoBitRateCalculator {
|
||||
return (int) (bytes * 8 / (durationMs / 1000f));
|
||||
}
|
||||
|
||||
public int getMaxVideoUploadDurationInSeconds() {
|
||||
long totalMinimumBitrate = VideoConstants.VIDEO_MINIMUM_TARGET_BIT_RATE + VideoConstants.AUDIO_BIT_RATE;
|
||||
return Math.toIntExact((upperFileSizeLimitWithMargin * 8) / totalMinimumBitrate);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -7,13 +7,16 @@ package org.thoughtcrime.securesms.video.videoconverter.utils
|
||||
|
||||
import android.media.MediaFormat
|
||||
object VideoConstants {
|
||||
const val AUDIO_BIT_RATE = 192000
|
||||
const val AUDIO_BIT_RATE = 192_000
|
||||
const val VIDEO_FRAME_RATE = 30
|
||||
const val VIDEO_BIT_RATE = 2000000
|
||||
const val VIDEO_TARGET_BIT_RATE = 2_000_000
|
||||
const val VIDEO_MINIMUM_TARGET_BIT_RATE = 500_000
|
||||
const val LOW_RES_TARGET_VIDEO_BITRATE = 1_750_000
|
||||
const val LOW_RES_OUTPUT_FORMAT = 480
|
||||
const val VIDEO_SHORT_EDGE = 720
|
||||
const val VIDEO_LONG_EDGE = 1280
|
||||
const val VIDEO_MAX_RECORD_LENGTH_S = 60
|
||||
const val TOTAL_BYTES_PER_SECOND = VIDEO_BIT_RATE / 8 + AUDIO_BIT_RATE / 8
|
||||
const val TOTAL_BYTES_PER_SECOND = VIDEO_TARGET_BIT_RATE / 8 + AUDIO_BIT_RATE / 8
|
||||
const val VIDEO_MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC
|
||||
const val AUDIO_MIME_TYPE = MediaFormat.MIMETYPE_AUDIO_AAC
|
||||
const val RECORDED_VIDEO_CONTENT_TYPE: String = "video/mp4"
|
||||
|
||||
Reference in New Issue
Block a user