Add streaming video support for attachment files.

This commit is contained in:
Clark
2024-05-21 21:00:36 -04:00
committed by Cody Henthorne
parent bc5cb454bf
commit 5c3ea712fe
4 changed files with 84 additions and 12 deletions

View File

@@ -116,6 +116,7 @@ import org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackPolicy;
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackPolicyEnforcer;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
import org.thoughtcrime.securesms.jobs.RestoreAttachmentJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory;
@@ -2489,7 +2490,22 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
}
if (MediaUtil.isInstantVideoSupported(slide)) {
final DatabaseAttachment databaseAttachment = (DatabaseAttachment) slide.asAttachment();
if (databaseAttachment.transferState != AttachmentTable.TRANSFER_PROGRESS_STARTED) {
if (databaseAttachment.transferState == AttachmentTable.TRANSFER_RESTORE_OFFLOADED) {
final AttachmentId attachmentId = databaseAttachment.attachmentId;
final JobManager jobManager = ApplicationDependencies.getJobManager();
final String queue = RestoreAttachmentJob.constructQueueString(attachmentId);
setup(v, slide);
jobManager.add(new RestoreAttachmentJob(messageRecord.getId(),
attachmentId,
true,
false,
RestoreAttachmentJob.RestoreMode.ORIGINAL));
jobManager.addListener(queue, (job, jobState) -> {
if (jobState.isComplete()) {
cleanup();
}
});
} else if (databaseAttachment.transferState != AttachmentTable.TRANSFER_PROGRESS_STARTED) {
final AttachmentId attachmentId = databaseAttachment.attachmentId;
final JobManager jobManager = ApplicationDependencies.getJobManager();
final String queue = AttachmentDownloadJob.constructQueueString(attachmentId);

View File

@@ -16,9 +16,14 @@ import org.signal.libsignal.protocol.InvalidMessageException;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mms.PartUriParser;
import org.signal.core.util.Base64;
import org.whispersystems.signalservice.api.backup.BackupKey;
import org.whispersystems.signalservice.api.backup.MediaId;
import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream;
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream;
import java.io.EOFException;
import java.io.File;
@@ -62,20 +67,30 @@ class PartDataSource implements DataSource {
if (inProgress && !hasData && hasIncrementalDigest && attachmentKey != null) {
final byte[] decode = Base64.decode(attachmentKey);
final File transferFile = attachmentDatabase.getOrCreateTransferFile(attachment.attachmentId);
try {
this.inputStream = AttachmentCipherInputStream.createForAttachment(transferFile, attachment.size, decode, attachment.remoteDigest, attachment.getIncrementalDigest(), attachment.incrementalMacChunkSize);
if (attachment.transferState == AttachmentTable.TRANSFER_RESTORE_IN_PROGRESS && attachment.archiveMediaId != null) {
final File archiveFile = attachmentDatabase.getOrCreateArchiveTransferFile(attachment.attachmentId);
try {
BackupKey.MediaKeyMaterial mediaKeyMaterial = SignalStore.svr().getOrCreateMasterKey().deriveBackupKey().deriveMediaSecretsFromMediaId(attachment.archiveMediaId);
long originalCipherLength = AttachmentCipherStreamUtil.getCiphertextLength(PaddingInputStream.getPaddedSize(attachment.size));
long skipped = 0;
while (skipped < dataSpec.position) {
skipped += this.inputStream.read();
this.inputStream = AttachmentCipherInputStream.createStreamingForArchivedAttachment(mediaKeyMaterial, archiveFile, originalCipherLength, attachment.size, attachment.remoteDigest, decode, attachment.getIncrementalDigest(), attachment.incrementalMacChunkSize);
} catch (InvalidMessageException e) {
throw new IOException("Error decrypting attachment stream!", e);
}
} else {
final File transferFile = attachmentDatabase.getOrCreateTransferFile(attachment.attachmentId);
try {
this.inputStream = AttachmentCipherInputStream.createForAttachment(transferFile, attachment.size, decode, attachment.remoteDigest, attachment.getIncrementalDigest(), attachment.incrementalMacChunkSize);
} catch (InvalidMessageException e) {
throw new IOException("Error decrypting attachment stream!", e);
}
Log.d(TAG, "Successfully loaded partial attachment file.");
} catch (InvalidMessageException e) {
throw new IOException("Error decrypting attachment stream!", e);
}
long skipped = 0;
while (skipped < dataSpec.position) {
skipped += this.inputStream.read();
}
Log.d(TAG, "Successfully loaded partial attachment file.");
} else if (!inProgress || hasData) {
this.inputStream = attachmentDatabase.getAttachmentStream(partUri.getPartId(), dataSpec.position);