Refactor Mp4FaststartPostProcessor.
This commit is contained in:
parent
8e7383be05
commit
7bb1c58452
4 changed files with 30 additions and 29 deletions
|
@ -42,10 +42,8 @@ import org.thoughtcrime.securesms.video.InMemoryTranscoder;
|
|||
import org.thoughtcrime.securesms.video.StreamingTranscoder;
|
||||
import org.thoughtcrime.securesms.video.TranscoderCancelationSignal;
|
||||
import org.thoughtcrime.securesms.video.TranscoderOptions;
|
||||
import org.thoughtcrime.securesms.video.exceptions.VideoPostProcessingException;
|
||||
import org.thoughtcrime.securesms.video.exceptions.VideoSourceException;
|
||||
import org.thoughtcrime.securesms.video.postprocessing.Mp4FaststartPostProcessor;
|
||||
import org.thoughtcrime.securesms.video.exceptions.VideoSourceException;
|
||||
import org.thoughtcrime.securesms.video.videoconverter.EncodingException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -263,7 +261,7 @@ public final class AttachmentCompressionJob extends BaseJob {
|
|||
Log.i(TAG, "Compressing with streaming muxer");
|
||||
AttachmentSecret attachmentSecret = AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret();
|
||||
|
||||
File file = SignalDatabase.attachments().newFile(context);
|
||||
File file = AttachmentTable.newFile(context);
|
||||
file.deleteOnExit();
|
||||
|
||||
boolean faststart = false;
|
||||
|
@ -291,9 +289,10 @@ public final class AttachmentCompressionJob extends BaseJob {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, file.length());
|
||||
});
|
||||
|
||||
try (MediaStream mediaStream = new MediaStream(postProcessor.process(), MimeTypes.VIDEO_MP4, 0, 0, true)) {
|
||||
final long plaintextLength = ModernEncryptingPartOutputStream.getPlaintextLength(file.length());
|
||||
try (MediaStream mediaStream = new MediaStream(postProcessor.process(plaintextLength), MimeTypes.VIDEO_MP4, 0, 0, true)) {
|
||||
attachmentDatabase.updateAttachmentData(attachment, mediaStream, true);
|
||||
faststart = true;
|
||||
}
|
||||
|
|
|
@ -179,9 +179,9 @@ public final class InMemoryTranscoder implements Closeable {
|
|||
Log.w(TAG, "IOException thrown while creating FileInputStream.", e);
|
||||
throw new VideoPostProcessingException("Exception while opening InputStream!", e);
|
||||
}
|
||||
}, memoryFile.size());
|
||||
});
|
||||
|
||||
return new MediaStream(postProcessor.process(), MimeTypes.VIDEO_MP4, 0, 0, true);
|
||||
return new MediaStream(postProcessor.process(outSize), MimeTypes.VIDEO_MP4, 0, 0, true);
|
||||
} catch (VideoPostProcessingException e) {
|
||||
Log.w(TAG, "Exception thrown during post processing.", e);
|
||||
final Throwable cause = e.getCause();
|
||||
|
|
|
@ -113,10 +113,7 @@ class TranscodeWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(
|
|||
return Result.failure()
|
||||
}
|
||||
|
||||
tempFileLength = tempFileStream.readLength() ?: run {
|
||||
Log.w(TAG, "$logPrefix Could not read file length of temp file descriptor!")
|
||||
return Result.failure()
|
||||
}
|
||||
tempFileLength = tempFileStream.readLength()
|
||||
}
|
||||
val finalFile = createFile(Uri.parse(outputDirUri), finalFilename) ?: run {
|
||||
Log.w(TAG, "$logPrefix Could not create final file for faststart processing!")
|
||||
|
@ -129,7 +126,7 @@ class TranscodeWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(
|
|||
}
|
||||
|
||||
val inputStreamFactory = { applicationContext.contentResolver.openInputStream(tempFile.uri) ?: throw IOException("Could not open temp file for reading!") }
|
||||
val bytesCopied = Mp4FaststartPostProcessor(inputStreamFactory, tempFileLength).processAndWriteTo(finalFileStream)
|
||||
val bytesCopied = Mp4FaststartPostProcessor(inputStreamFactory).processAndWriteTo(finalFileStream)
|
||||
|
||||
if (bytesCopied != tempFileLength) {
|
||||
Log.w(TAG, "$logPrefix Postprocessing failed! Original transcoded filesize ($tempFileLength) did not match postprocessed filesize ($bytesCopied)")
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
package org.thoughtcrime.securesms.video.postprocessing
|
||||
|
||||
import org.signal.core.util.readLength
|
||||
import org.signal.libsignal.media.Mp4Sanitizer
|
||||
import org.signal.libsignal.media.SanitizedMetadata
|
||||
import org.thoughtcrime.securesms.video.exceptions.VideoPostProcessingException
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.FilterInputStream
|
||||
import java.io.IOException
|
||||
|
@ -18,31 +18,22 @@ import java.io.SequenceInputStream
|
|||
/**
|
||||
* A post processor that takes a stream of bytes, and using [Mp4Sanitizer], moves the metadata to the front of the file.
|
||||
*
|
||||
* @property inputStreamFactory factory for the [InputStream]. May be called multiple times.
|
||||
* @property inputLength the exact length of the [InputStream]
|
||||
* @property inputStreamFactory factory for the [InputStream]. Expected to be called multiple times.
|
||||
*/
|
||||
class Mp4FaststartPostProcessor(private val inputStreamFactory: InputStreamFactory, private val inputLength: Long) {
|
||||
class Mp4FaststartPostProcessor(private val inputStreamFactory: InputStreamFactory) {
|
||||
|
||||
/**
|
||||
* It is the responsibility of the called to close the resulting [InputStream]
|
||||
* It is the responsibility of the caller to close the resulting [InputStream].
|
||||
*/
|
||||
fun process(): InputStream {
|
||||
val metadata: SanitizedMetadata?
|
||||
inputStreamFactory.create().use {
|
||||
metadata = Mp4Sanitizer.sanitize(it, inputLength)
|
||||
}
|
||||
if (metadata?.sanitizedMetadata == null) {
|
||||
throw VideoPostProcessingException("Mp4Sanitizer could not parse media metadata!")
|
||||
}
|
||||
|
||||
fun process(inputLength: Long = calculateStreamLength(inputStreamFactory.create())): SequenceInputStream {
|
||||
val metadata = sanitizeMetadata(inputStreamFactory.create(), inputLength)
|
||||
val inputStream = inputStreamFactory.create()
|
||||
inputStream.skip(metadata.dataOffset)
|
||||
|
||||
return SequenceInputStream(ByteArrayInputStream(metadata.sanitizedMetadata), LimitedInputStream(inputStream, metadata.dataLength))
|
||||
}
|
||||
|
||||
fun processAndWriteTo(outputStream: OutputStream): Long {
|
||||
process().use { inStream ->
|
||||
fun processAndWriteTo(outputStream: OutputStream, inputLength: Long = calculateStreamLength(inputStreamFactory.create())): Long {
|
||||
process(inputLength).use { inStream ->
|
||||
return inStream.copyTo(outputStream)
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +44,20 @@ class Mp4FaststartPostProcessor(private val inputStreamFactory: InputStreamFacto
|
|||
|
||||
companion object {
|
||||
const val TAG = "Mp4Faststart"
|
||||
|
||||
@JvmStatic
|
||||
fun calculateStreamLength(inputStream: InputStream): Long {
|
||||
inputStream.use {
|
||||
return it.readLength()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
private fun sanitizeMetadata(inputStream: InputStream, inputLength: Long): SanitizedMetadata {
|
||||
inputStream.use {
|
||||
return Mp4Sanitizer.sanitize(it, inputLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LimitedInputStream(innerStream: InputStream, limit: Long) : FilterInputStream(innerStream) {
|
||||
|
|
Loading…
Add table
Reference in a new issue