diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt index b14b17dc01..ea9c3dcc0c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt @@ -101,8 +101,9 @@ class DefaultMediaOptimizationSelectorPresenter @AssistedInject constructor( val sizeEstimations = VideoCompressionPreset.entries .map { preset -> - val bitRate = preset.compressorHelper().calculateOptimalBitrate(videoDimensions, 30) - val calculatedSize = (bitRate * duration / 8 * 1.1).roundToLong() // Adding 10% overhead for safety + val bitRateAsBytes = preset.compressorHelper().calculateOptimalBitrate(videoDimensions, 30) / 8f + val durationInSeconds = duration.inWholeSeconds.toFloat() + val calculatedSize = (bitRateAsBytes * durationInSeconds * 1.1f).roundToLong() // Adding 10% overhead for safety VideoUploadEstimation( preset = preset, sizeInBytes = calculatedSize, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt index e8f30043ef..0567bfeffc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt @@ -18,10 +18,12 @@ import dagger.assisted.AssistedInject import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.ApplicationContext +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds interface VideoMetadataExtractor : AutoCloseable { fun getSize(): Result - fun getDuration(): Result + fun getDuration(): Result interface Factory { fun create(uri: Uri): VideoMetadataExtractor } @@ -57,9 +59,10 @@ class DefaultVideoMetadataExtractor @AssistedInject constructor( } } - override fun getDuration(): Result = runCatchingExceptions { + override fun getDuration(): Result = runCatchingExceptions { mediaMetadataRetriever.value.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?.takeIf { it > 0L } + ?.milliseconds ?: error("Could not retrieve video duration from metadata") } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt index b529918ddc..d095f0d58a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import kotlin.time.Duration.Companion.minutes @RunWith(AndroidJUnit4::class) class DefaultMediaOptimizationSelectorPresenterTest { @@ -158,7 +159,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { mediaExtractorFactory = FakeVideoMetadataExtractorFactory( FakeVideoMetadataExtractor( sizeResult = Result.success(Size(10_000, 10_000)), - duration = Result.success(600L) + duration = Result.success(10.minutes) ) ), ) diff --git a/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeVideoMetadataExtractor.kt b/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeVideoMetadataExtractor.kt index 54b27ac675..45d3e31dfb 100644 --- a/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeVideoMetadataExtractor.kt +++ b/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeVideoMetadataExtractor.kt @@ -10,14 +10,16 @@ package io.element.android.features.messages.test.attachments.video import android.net.Uri import android.util.Size import io.element.android.features.messages.impl.attachments.video.VideoMetadataExtractor +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds class FakeVideoMetadataExtractor( private val sizeResult: Result = Result.success(Size(1, 1)), - private val duration: Result = Result.success(1L), + private val duration: Result = Result.success(1.milliseconds), ) : VideoMetadataExtractor { override fun getSize(): Result = sizeResult - override fun getDuration(): Result = duration + override fun getDuration(): Result = duration override fun close() = Unit } diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt index a9aa8cf378..91953a22a3 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt @@ -38,7 +38,7 @@ class VideoCompressorHelper( val pixelsPerFrame = outputSize.width * outputSize.height // Apparently, 0.1 bits per pixel is a sweet spot for video compression val bitsPerPixel = 0.1f - return (pixelsPerFrame * bitsPerPixel * frameRate).toLong() / 1000 + return (pixelsPerFrame * bitsPerPixel * frameRate).toLong() } }