diff --git a/video/lib/src/main/java/org/thoughtcrime/securesms/video/videoconverter/VideoTrackConverter.java b/video/lib/src/main/java/org/thoughtcrime/securesms/video/videoconverter/VideoTrackConverter.java index a00bd8ae68..726ac9528c 100644 --- a/video/lib/src/main/java/org/thoughtcrime/securesms/video/videoconverter/VideoTrackConverter.java +++ b/video/lib/src/main/java/org/thoughtcrime/securesms/video/videoconverter/VideoTrackConverter.java @@ -13,6 +13,7 @@ import androidx.annotation.RequiresApi; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.video.interfaces.MediaInput; import org.thoughtcrime.securesms.video.interfaces.Muxer; +import org.thoughtcrime.securesms.video.videoconverter.utils.Extensions; import org.thoughtcrime.securesms.video.videoconverter.utils.Preconditions; import java.io.FileNotFoundException; @@ -34,6 +35,8 @@ final class VideoTrackConverter { private static final String MEDIA_FORMAT_KEY_DISPLAY_WIDTH = "display-width"; private static final String MEDIA_FORMAT_KEY_DISPLAY_HEIGHT = "display-height"; + private static final float FRAME_RATE_TOLERANCE = 0.05f; // tolerance for transcoding VFR -> CFR + private final long mTimeFrom; private final long mTimeTo; @@ -420,7 +423,7 @@ final class VideoTrackConverter { } void verifyEndState() { - Preconditions.checkState("encoded (" + mVideoEncodedFrameCount + ") and decoded (" + mVideoDecodedFrameCount + ") video frame counts should match", mVideoDecodedFrameCount == mVideoEncodedFrameCount); + Preconditions.checkState("encoded (" + mVideoEncodedFrameCount + ") and decoded (" + mVideoDecodedFrameCount + ") video frame counts should match", Extensions.isWithin(mVideoDecodedFrameCount, mVideoEncodedFrameCount, FRAME_RATE_TOLERANCE)); Preconditions.checkState("decoded frame count should be less than extracted frame count", mVideoDecodedFrameCount <= mVideoExtractedFrameCount); } diff --git a/video/lib/src/main/java/org/thoughtcrime/securesms/video/videoconverter/utils/Extensions.kt b/video/lib/src/main/java/org/thoughtcrime/securesms/video/videoconverter/utils/Extensions.kt new file mode 100644 index 0000000000..6ff085c63c --- /dev/null +++ b/video/lib/src/main/java/org/thoughtcrime/securesms/video/videoconverter/utils/Extensions.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.video.videoconverter.utils + +import kotlin.math.ceil +import kotlin.math.floor +import kotlin.math.roundToLong + +object Extensions { + /** + * Determines if the [actual] value is close enough to the [expected] value within the [tolerance] + * + * @param tolerance a float value, where 0f defines an exact match, 0.1f defines a 10% tolerance, etc. + */ + @JvmStatic + fun isWithin(expected: Long, actual: Long, tolerance: Float): Boolean { + val floor = floor(expected * (1 - tolerance)).roundToLong() + val ceiling = ceil(expected * (1 + tolerance)).roundToLong() + return actual in floor..ceiling + } +}