diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index aa181b417..025a50e91 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -1018,19 +1018,22 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity DcMsg msg = (DcMsg)param[0]; Integer recompress = (Integer)param[1]; if (action==ACTION_SEND_OUT) { + dcContext.setDraft(dcChat.getId(), null); + if(msg!=null) { if(recompress!=0) { + if(recompress==DcMsg.DC_MSG_IMAGE) { BitmapUtil.recodeImageMsg(ConversationActivity.this, msg); } else if(recompress==DcMsg.DC_MSG_VIDEO) { - VideoRecoder.recodeVideo(ConversationActivity.this, msg); + VideoRecoder.prepareVideo(ConversationActivity.this, dcChat.getId(), msg); } } + dcContext.sendMsg(dcChat.getId(), msg); Util.runOnMain(()-> sendComplete(dcChat.getId())); } - dcContext.setDraft(dcChat.getId(), null); } else { dcContext.setDraft(dcChat.getId(), msg); diff --git a/src/org/thoughtcrime/securesms/util/Util.java b/src/org/thoughtcrime/securesms/util/Util.java index 140bd0475..cc71ba643 100644 --- a/src/org/thoughtcrime/securesms/util/Util.java +++ b/src/org/thoughtcrime/securesms/util/Util.java @@ -43,6 +43,9 @@ import org.thoughtcrime.securesms.components.ComposeText; import org.thoughtcrime.securesms.database.Address; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -180,6 +183,39 @@ public class Util { return total; } + public static boolean moveFile(String fromPath, String toPath) { + boolean success = false; + + // 1st try: a simple rename + try { + File fromFile = new File(fromPath); + File toFile = new File(toPath); + toFile.delete(); + if(fromFile.renameTo(toFile)) { + success = true; + } + } + catch (Exception e) { + e.printStackTrace(); + } + + // 2nd try: copy file + if (!success) { + try { + InputStream fromStream = new FileInputStream(fromPath); + OutputStream toStream = new FileOutputStream(toPath); + if(Util.copy(fromStream, toStream)>0) { + success = true; + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + return success; + } + public static List split(String source, String delimiter) { List results = new LinkedList<>(); diff --git a/src/org/thoughtcrime/securesms/video/recode/VideoRecoder.java b/src/org/thoughtcrime/securesms/video/recode/VideoRecoder.java index 263dcb956..52f61b862 100644 --- a/src/org/thoughtcrime/securesms/video/recode/VideoRecoder.java +++ b/src/org/thoughtcrime/securesms/video/recode/VideoRecoder.java @@ -23,6 +23,7 @@ import com.googlecode.mp4parser.util.Matrix; import com.googlecode.mp4parser.util.Path; import org.thoughtcrime.securesms.connect.DcHelper; +import org.thoughtcrime.securesms.util.Util; import java.io.File; import java.nio.ByteBuffer; @@ -757,17 +758,22 @@ public class VideoRecoder { return size; } - public static boolean recodeVideo(Context context, DcMsg msg) { - - if (!canRecode()) { - return false; - } + // prepareVideo() assumes the msg object is set up properly to being sent; + // the function fills out missing information and also recodes the video as needed; + // to get a responsive ui, DcChat.prepareMsg() may be called. + public static void prepareVideo(Context context, int chatId, DcMsg msg) { String inPath = msg.getFile(); + if (!canRecode()) { + Log.w(TAG, String.format("recoding for %s failed: this system cannot recode videos", inPath)); + return; + } + VideoEditedInfo vei = getVideoEditInfoFromFile(inPath); if(vei==null) { - return false; + Log.w(TAG, String.format("recoding for %s failed: cannot get info", inPath)); + return; } vei.rotationValue = vei.originalRotationValue; @@ -795,7 +801,7 @@ public class VideoRecoder { } } - // get video dimensions + // calculate video dimensions int maxSide = vei.resultBitrate>400000? 640 : 480; vei.resultWidth = vei.originalWidth; vei.resultHeight = vei.originalHeight; @@ -805,21 +811,7 @@ public class VideoRecoder { vei.resultHeight *= scale; } - // calulate bytes - vei.estimatedBytes = VideoRecoder.calculateEstimatedSize((float) resultDurationMs / vei.originalDurationMs, - vei.resultBitrate, vei.originalDurationMs, vei.originalAudioBytes); - - if(vei.estimatedBytes>MAX_BYTES) { - return false; - } - - String outPath = DcHelper.getContext(context).getBlobdirFile(inPath); - VideoRecoder videoRecoder = new VideoRecoder(); - if (!videoRecoder.convertVideo(vei, outPath)) { - return false; - } - - msg.setFile(outPath, null); + // we know the most important things now, prepare the message to get a resposive ui if(vei.originalRotationValue==90||vei.originalRotationValue==270) { msg.setDimension(vei.resultHeight, vei.resultWidth); } @@ -827,8 +819,30 @@ public class VideoRecoder { msg.setDimension(vei.resultWidth, vei.resultHeight); } msg.setDuration((int)resultDurationMs); + DcHelper.getContext(context).prepareMsg(chatId, msg); + + // calulate bytes + vei.estimatedBytes = VideoRecoder.calculateEstimatedSize((float) resultDurationMs / vei.originalDurationMs, + vei.resultBitrate, vei.originalDurationMs, vei.originalAudioBytes); + + if(vei.estimatedBytes>MAX_BYTES) { + Log.w(TAG, String.format("recoding for %s: resulting file may too large", inPath)); + // continue anyway + } + + // recode + String tempPath = DcHelper.getContext(context).getBlobdirFile(inPath); + VideoRecoder videoRecoder = new VideoRecoder(); + if (!videoRecoder.convertVideo(vei, tempPath)) { + Log.w(TAG, String.format("recoding for %s failed: cannot convert to temporary file %s", inPath, tempPath)); + return; + } + + if(!Util.moveFile(tempPath, inPath)) { + Log.w(TAG, String.format("recoding for %s failed: cannot move temporary file %s", inPath, tempPath)); + return; + } Log.i(TAG, String.format("recoding for %s done", inPath)); - return true; } }