Fix video sample app output.

This commit is contained in:
Nicholas Tinsley 2024-01-16 16:22:33 -05:00 committed by Greyson Parrelli
parent 2194fbd535
commit 393730cea9
2 changed files with 43 additions and 25 deletions

View file

@ -22,13 +22,13 @@ import androidx.work.ForegroundInfo
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import org.signal.core.util.getLength
import org.signal.core.util.readLength
import org.thoughtcrime.securesms.video.StreamingTranscoder
import org.thoughtcrime.securesms.video.postprocessing.Mp4FaststartPostProcessor
import org.thoughtcrime.securesms.video.videoconverter.VideoConstants
import org.thoughtcrime.securesms.video.videoconverter.mediadatasource.InputStreamMediaDataSource
import org.thoughtcrime.video.app.R
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.time.Instant
@ -90,45 +90,55 @@ class TranscodeWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(
}
setForeground(createForegroundInfo(-1, notificationId))
applicationContext.contentResolver.openFileDescriptor(tempFile.uri, "w").use { tempFd ->
if (tempFd == null) {
applicationContext.contentResolver.openOutputStream(tempFile.uri).use { outputStream ->
if (outputStream == null) {
Log.w(TAG, "$logPrefix Could not open temp file for I/O!")
return Result.failure()
}
transcoder.transcode({ percent: Int ->
setProgressAsync(Data.Builder().putInt(KEY_PROGRESS, percent).build())
setForegroundAsync(createForegroundInfo(percent, notificationId))
}, FileOutputStream(tempFd.fileDescriptor), { isStopped })
}, outputStream, { isStopped })
}
Log.v(TAG, "$logPrefix Initial transcode completed successfully!")
if (!postProcessForFastStart) {
tempFile.renameTo(finalFilename)
Log.v(TAG, "$logPrefix Rename successful.")
} else {
applicationContext.contentResolver.openFileDescriptor(tempFile.uri, "r").use { tempFd ->
if (tempFd == null) {
val tempFileLength: Long
applicationContext.contentResolver.openInputStream(tempFile.uri).use { tempFileStream ->
if (tempFileStream == null) {
Log.w(TAG, "$logPrefix Could not open temp file for I/O!")
return Result.failure()
}
val finalFile = createFile(Uri.parse(outputDirUri), finalFilename)
if (finalFile == null) {
Log.w(TAG, "$logPrefix Could not create final file for faststart processing!")
tempFileLength = tempFileStream.readLength() ?: run {
Log.w(TAG, "$logPrefix Could not read file length of temp file descriptor!")
return Result.failure()
}
}
val finalFile = createFile(Uri.parse(outputDirUri), finalFilename) ?: run {
Log.w(TAG, "$logPrefix Could not create final file for faststart processing!")
return Result.failure()
}
applicationContext.contentResolver.openOutputStream(finalFile.uri, "w").use { finalFileStream ->
if (finalFileStream == null) {
Log.w(TAG, "$logPrefix Could not open output file for I/O!")
return Result.failure()
}
applicationContext.contentResolver.openFileDescriptor(finalFile.uri, "w").use { finalFd ->
if (finalFd == null) {
Log.w(TAG, "$logPrefix Could not open output file for I/O!")
return Result.failure()
}
Mp4FaststartPostProcessor({ FileInputStream(tempFd.fileDescriptor) }, tempFd.statSize).processAndWriteTo(FileOutputStream(finalFd.fileDescriptor))
val inputStreamFactory = { applicationContext.contentResolver.openInputStream(tempFile.uri) ?: throw IOException("Could not open temp file for reading!") }
val bytesCopied = Mp4FaststartPostProcessor(inputStreamFactory, tempFileLength).processAndWriteTo(finalFileStream)
if (!tempFile.delete()) {
Log.w(TAG, "$logPrefix Failed to delete temp file after processing!")
return Result.failure()
}
if (bytesCopied != tempFileLength) {
Log.w(TAG, "$logPrefix Postprocessing failed! Original transcoded filesize ($tempFileLength) did not match postprocessed filesize ($bytesCopied)")
return Result.failure()
}
if (!tempFile.delete()) {
Log.w(TAG, "$logPrefix Failed to delete temp file after processing!")
return Result.failure()
}
}
Log.v(TAG, "$logPrefix Faststart postprocess successful.")

View file

@ -21,9 +21,15 @@ import java.io.SequenceInputStream
* @property inputLength the exact stream of the [InputStream]
*/
class Mp4FaststartPostProcessor(private val inputStreamFactory: () -> InputStream, private val inputLength: Long) {
fun process(): InputStream {
val metadata: SanitizedMetadata? = Mp4Sanitizer.sanitize(inputStreamFactory(), inputLength)
/**
* It is the responsibility of the called to close the resulting [InputStream]
*/
fun process(): InputStream {
val metadata: SanitizedMetadata?
inputStreamFactory().use {
metadata = Mp4Sanitizer.sanitize(it, inputLength)
}
if (metadata?.sanitizedMetadata == null) {
throw VideoPostProcessingException("Mp4Sanitizer could not parse media metadata!")
}
@ -33,8 +39,10 @@ class Mp4FaststartPostProcessor(private val inputStreamFactory: () -> InputStrea
return SequenceInputStream(ByteArrayInputStream(metadata.sanitizedMetadata), ByteStreams.limit(inputStream, metadata.dataLength))
}
fun processAndWriteTo(outputStream: OutputStream) {
process().copyTo(outputStream)
fun processAndWriteTo(outputStream: OutputStream): Long {
process().use { inStream ->
return inStream.copyTo(outputStream)
}
}
companion object {