Handle missing video duration.
On EncodingException, or no duration metadata found, when video < 100MB, continue with send.
This commit is contained in:
parent
9d98a779a8
commit
929ee04814
4 changed files with 57 additions and 9 deletions
|
@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||||
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
import org.thoughtcrime.securesms.mms.MediaStream;
|
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.BitmapUtil;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.video.InMemoryTranscoder;
|
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 org.thoughtcrime.securesms.video.videoconverter.EncodingException;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
@ -31,6 +34,8 @@ import java.util.List;
|
||||||
|
|
||||||
final class MediaResizer {
|
final class MediaResizer {
|
||||||
|
|
||||||
|
private static final String TAG = Log.tag(MediaResizer.class);
|
||||||
|
|
||||||
@NonNull private final Context context;
|
@NonNull private final Context context;
|
||||||
@NonNull private final MediaConstraints constraints;
|
@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);
|
throw new UndeliverableMessageException("Failed to transcode", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.mms.MediaStream;
|
import org.thoughtcrime.securesms.mms.MediaStream;
|
||||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
|
||||||
import org.thoughtcrime.securesms.util.MemoryFileDescriptor;
|
import org.thoughtcrime.securesms.util.MemoryFileDescriptor;
|
||||||
import org.thoughtcrime.securesms.video.videoconverter.EncodingException;
|
import org.thoughtcrime.securesms.video.videoconverter.EncodingException;
|
||||||
import org.thoughtcrime.securesms.video.videoconverter.MediaConverter;
|
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.
|
* @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.context = context;
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
|
|
||||||
final MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
|
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);
|
long upperSizeLimitWithMargin = (long) (upperSizeLimit / 1.1);
|
||||||
|
|
||||||
|
@ -80,7 +84,7 @@ public final class InMemoryTranscoder implements Closeable {
|
||||||
: OUTPUT_FORMAT;
|
: 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");
|
if (memoryFile != null) throw new AssertionError("Not expecting to reuse transcoder");
|
||||||
|
|
||||||
float durationSec = duration / 1000f;
|
float durationSec = duration / 1000f;
|
||||||
|
@ -107,7 +111,7 @@ public final class InMemoryTranscoder implements Closeable {
|
||||||
numberFormat.format(inputBitRate)));
|
numberFormat.format(inputBitRate)));
|
||||||
|
|
||||||
if (fileSizeEstimate > upperSizeLimit) {
|
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,
|
memoryFile = MemoryFileDescriptor.newMemoryFileDescriptor(context,
|
||||||
|
@ -153,7 +157,7 @@ public final class InMemoryTranscoder implements Closeable {
|
||||||
numberFormat.format(bitRate(outSize, duration))));
|
numberFormat.format(bitRate(outSize, duration))));
|
||||||
|
|
||||||
if (outSize > upperSizeLimit) {
|
if (outSize > upperSizeLimit) {
|
||||||
throw new UndeliverableMessageException("Size constraints could not be met!");
|
throw new VideoSizeException("Size constraints could not be met!");
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryFile.seek(0);
|
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));
|
return Math.max(MINIMUM_TARGET_VIDEO_BITRATE, Math.min(MAXIMUM_TARGET_VIDEO_BITRATE, (int) bitRateToFixTarget));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getDuration(MediaMetadataRetriever mediaMetadataRetriever) {
|
private static long getDuration(MediaMetadataRetriever mediaMetadataRetriever) throws VideoSourceException {
|
||||||
return Long.parseLong(mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
|
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) {
|
private static boolean containsLocation(MediaMetadataRetriever mediaMetadataRetriever) {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.thoughtcrime.securesms.video;
|
||||||
|
|
||||||
|
public final class VideoSizeException extends Exception {
|
||||||
|
|
||||||
|
VideoSizeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue