Handle missing video duration.

On EncodingException, or no duration metadata found, when video < 100MB, continue with send.
This commit is contained in:
Alan Evans 2019-08-05 10:48:18 -04:00 committed by GitHub
parent 9d98a779a8
commit 929ee04814
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 9 deletions

View file

@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MediaStream;
@ -22,6 +23,8 @@ import org.thoughtcrime.securesms.util.BitmapDecodingException;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.video.InMemoryTranscoder;
import org.thoughtcrime.securesms.video.VideoSourceException;
import org.thoughtcrime.securesms.video.VideoSizeException;
import org.thoughtcrime.securesms.video.videoconverter.EncodingException;
import java.io.ByteArrayInputStream;
@ -31,6 +34,8 @@ import java.util.List;
final class MediaResizer {
private static final String TAG = Log.tag(MediaResizer.class);
@NonNull private final Context context;
@NonNull private final MediaConstraints constraints;
@ -114,7 +119,14 @@ final class MediaResizer {
}
}
}
} catch (IOException | MmsException | EncodingException e) {
} catch (VideoSourceException | EncodingException e) {
if (attachment.getSize() > constraints.getVideoMaxSize(context)) {
throw new UndeliverableMessageException("Duration not found, attachment too large to skip transcode", e);
} else {
Log.w(TAG, "Duration not found, video small enough to skip transcode", e);
return attachment;
}
} catch (IOException | MmsException | VideoSizeException e) {
throw new UndeliverableMessageException("Failed to transcode", e);
}
}

View file

@ -12,7 +12,6 @@ import com.google.android.exoplayer2.util.MimeTypes;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.MediaStream;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.MemoryFileDescriptor;
import org.thoughtcrime.securesms.video.videoconverter.EncodingException;
import org.thoughtcrime.securesms.video.videoconverter.MediaConverter;
@ -53,12 +52,17 @@ public final class InMemoryTranscoder implements Closeable {
/**
* @param upperSizeLimit A upper size to transcode to. The actual output size can be up to 10% smaller.
*/
public InMemoryTranscoder(@NonNull Context context, @NonNull MediaDataSource dataSource, long upperSizeLimit) throws IOException {
public InMemoryTranscoder(@NonNull Context context, @NonNull MediaDataSource dataSource, long upperSizeLimit) throws IOException, VideoSourceException {
this.context = context;
this.dataSource = dataSource;
final MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(dataSource);
try {
mediaMetadataRetriever.setDataSource(dataSource);
} catch (RuntimeException e) {
Log.w(TAG, "Unable to read datasource", e);
throw new VideoSourceException("Unable to read datasource", e);
}
long upperSizeLimitWithMargin = (long) (upperSizeLimit / 1.1);
@ -80,7 +84,7 @@ public final class InMemoryTranscoder implements Closeable {
: OUTPUT_FORMAT;
}
public @NonNull MediaStream transcode(@NonNull Progress progress) throws IOException, UndeliverableMessageException, EncodingException {
public @NonNull MediaStream transcode(@NonNull Progress progress) throws IOException, EncodingException, VideoSizeException {
if (memoryFile != null) throw new AssertionError("Not expecting to reuse transcoder");
float durationSec = duration / 1000f;
@ -107,7 +111,7 @@ public final class InMemoryTranscoder implements Closeable {
numberFormat.format(inputBitRate)));
if (fileSizeEstimate > upperSizeLimit) {
throw new UndeliverableMessageException("Size constraints could not be met!");
throw new VideoSizeException("Size constraints could not be met!");
}
memoryFile = MemoryFileDescriptor.newMemoryFileDescriptor(context,
@ -153,7 +157,7 @@ public final class InMemoryTranscoder implements Closeable {
numberFormat.format(bitRate(outSize, duration))));
if (outSize > upperSizeLimit) {
throw new UndeliverableMessageException("Size constraints could not be met!");
throw new VideoSizeException("Size constraints could not be met!");
}
memoryFile.seek(0);
@ -185,8 +189,20 @@ public final class InMemoryTranscoder implements Closeable {
return Math.max(MINIMUM_TARGET_VIDEO_BITRATE, Math.min(MAXIMUM_TARGET_VIDEO_BITRATE, (int) bitRateToFixTarget));
}
private static long getDuration(MediaMetadataRetriever mediaMetadataRetriever) {
return Long.parseLong(mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
private static long getDuration(MediaMetadataRetriever mediaMetadataRetriever) throws VideoSourceException {
String durationString = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
if (durationString == null) {
throw new VideoSourceException("Cannot determine duration of video, null meta data");
}
try {
long duration = Long.parseLong(durationString);
if (duration <= 0) {
throw new VideoSourceException("Cannot determine duration of video, meta data: " + durationString);
}
return duration;
} catch (NumberFormatException e) {
throw new VideoSourceException("Cannot determine duration of video, meta data: " + durationString, e);
}
}
private static boolean containsLocation(MediaMetadataRetriever mediaMetadataRetriever) {

View file

@ -0,0 +1,8 @@
package org.thoughtcrime.securesms.video;
public final class VideoSizeException extends Exception {
VideoSizeException(String message) {
super(message);
}
}

View file

@ -0,0 +1,12 @@
package org.thoughtcrime.securesms.video;
public final class VideoSourceException extends Exception {
VideoSourceException(String message) {
super(message);
}
VideoSourceException(String message, Exception inner) {
super(message, inner);
}
}