mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Standardize percentage calculations
This is a follow-up to 72f5df582a
PiperOrigin-RevId: 743173295
This commit is contained in:
parent
0dd43b0183
commit
a9c0349214
@ -321,7 +321,7 @@ public abstract class BasePlayer implements Player {
|
||||
long duration = getDuration();
|
||||
return position == C.TIME_UNSET || duration == C.TIME_UNSET
|
||||
? 0
|
||||
: duration == 0 ? 100 : Util.constrainValue((int) ((position * 100) / duration), 0, 100);
|
||||
: duration == 0 ? 100 : Util.constrainValue(Util.percentInt(position, duration), 0, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1224,15 +1224,26 @@ public final class Util {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the percentage of numerator divided by denominator. Note that this may return {@link
|
||||
* Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY} or {@link Float#NaN} if the
|
||||
* denominator is zero.
|
||||
*
|
||||
* @param numerator The numerator.
|
||||
* @param denominator The denominator.
|
||||
* Returns the integer percentage of {@code numerator} divided by {@code denominator}. This uses
|
||||
* integer arithmetic (round down).
|
||||
*/
|
||||
@UnstableApi
|
||||
public static float percent(long numerator, long denominator) {
|
||||
public static int percentInt(long numerator, long denominator) {
|
||||
long numeratorTimes100 = LongMath.saturatedMultiply(numerator, 100);
|
||||
long result =
|
||||
numeratorTimes100 != Long.MAX_VALUE && numeratorTimes100 != Long.MIN_VALUE
|
||||
? numeratorTimes100 / denominator
|
||||
: (numerator / (denominator / 100));
|
||||
return Ints.checkedCast(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the floating point percentage of {@code numerator} divided by {@code denominator}. Note
|
||||
* that this may return {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY} or {@link
|
||||
* Float#NaN} if the denominator is zero.
|
||||
*/
|
||||
@UnstableApi
|
||||
public static float percentFloat(long numerator, long denominator) {
|
||||
if (denominator != 0 && numerator == denominator) {
|
||||
return 100f;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import static androidx.media3.common.util.Util.maxValue;
|
||||
import static androidx.media3.common.util.Util.minValue;
|
||||
import static androidx.media3.common.util.Util.parseXsDateTime;
|
||||
import static androidx.media3.common.util.Util.parseXsDuration;
|
||||
import static androidx.media3.common.util.Util.percent;
|
||||
import static androidx.media3.common.util.Util.percentFloat;
|
||||
import static androidx.media3.common.util.Util.unescapeFileName;
|
||||
import static androidx.media3.test.utils.TestUtil.buildTestData;
|
||||
import static androidx.media3.test.utils.TestUtil.buildTestString;
|
||||
@ -149,31 +149,53 @@ public class UtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percent_numeratorEqualToDenominator_returnsOneHundred() {
|
||||
public void percentInt_smallValues() {
|
||||
assertThat(Util.percentInt(3, 9)).isEqualTo(33);
|
||||
assertThat(Util.percentInt(3, 3)).isEqualTo(100);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentInt_smallNegativeValues() {
|
||||
assertThat(Util.percentInt(-3, -9)).isEqualTo(33);
|
||||
assertThat(Util.percentInt(-3, -3)).isEqualTo(100);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentInt_largeValuesDontOverflow() {
|
||||
assertThat(Util.percentInt(Long.MAX_VALUE / 4, Long.MAX_VALUE / 2)).isEqualTo(50);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentInt_largeNegativeValuesDontOverflow() {
|
||||
assertThat(Util.percentInt(Long.MIN_VALUE / 4, Long.MIN_VALUE / 2)).isEqualTo(50);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentFloat_numeratorEqualToDenominator_returnsOneHundred() {
|
||||
// With numerator and denominator both being 812345L, the percentage calculated in another way
|
||||
// (numerator * 100f / denominator) will be 99.99999f. We then use this value to verify that
|
||||
// this doesn't happen for Util.percent() method.
|
||||
assertThat(percent(812345L, 812345L)).isEqualTo(100f);
|
||||
assertThat(percentFloat(812345L, 812345L)).isEqualTo(100f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percent_numeratorNotEqualToDenominator_returnsCorrectValue() {
|
||||
assertThat(percent(500L, 2000L)).isEqualTo(25f);
|
||||
public void percentFloat_numeratorNotEqualToDenominator_returnsCorrectValue() {
|
||||
assertThat(percentFloat(500L, 2000L)).isEqualTo(25f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percent_positiveNumeratorAndZeroDenominator_returnsPositiveInfinity() {
|
||||
assertThat(percent(1L, 0L)).isPositiveInfinity();
|
||||
public void percentFloat_positiveNumeratorAndZeroDenominator_returnsPositiveInfinity() {
|
||||
assertThat(percentFloat(1L, 0L)).isPositiveInfinity();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percent_negativeNumeratorAndZeroDenominator_returnsNegativeInfinity() {
|
||||
assertThat(percent(-1L, 0L)).isNegativeInfinity();
|
||||
public void percentFloat_negativeNumeratorAndZeroDenominator_returnsNegativeInfinity() {
|
||||
assertThat(percentFloat(-1L, 0L)).isNegativeInfinity();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percent_numeratorAndDenominatorAreBothZero_returnsNaN() {
|
||||
assertThat(percent(0L, 0L)).isNaN();
|
||||
public void percentFloat_numeratorAndDenominatorAreBothZero_returnsNaN() {
|
||||
assertThat(percentFloat(0L, 0L)).isNaN();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -17,7 +17,7 @@ package androidx.media3.exoplayer.offline;
|
||||
|
||||
import static androidx.annotation.VisibleForTesting.PRIVATE;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Util.percent;
|
||||
import static androidx.media3.common.util.Util.percentFloat;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@ -217,7 +217,7 @@ public final class ProgressiveDownloader implements Downloader {
|
||||
float percentDownloaded =
|
||||
contentLength == C.LENGTH_UNSET || contentLength == 0
|
||||
? C.PERCENTAGE_UNSET
|
||||
: percent(bytesCached, contentLength);
|
||||
: percentFloat(bytesCached, contentLength);
|
||||
checkNotNull(progressListener).onProgress(contentLength, bytesCached, percentDownloaded);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package androidx.media3.exoplayer.offline;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Util.percent;
|
||||
import static androidx.media3.common.util.Util.percentFloat;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -537,9 +537,9 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
|
||||
|
||||
private float getPercentDownloaded() {
|
||||
if (contentLength != C.LENGTH_UNSET && contentLength != 0) {
|
||||
return percent(bytesDownloaded, contentLength);
|
||||
return percentFloat(bytesDownloaded, contentLength);
|
||||
} else if (totalSegments != 0) {
|
||||
return percent(segmentsDownloaded, totalSegments);
|
||||
return percentFloat(segmentsDownloaded, totalSegments);
|
||||
} else {
|
||||
return C.PERCENTAGE_UNSET;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ import java.util.List;
|
||||
? 0
|
||||
: durationMs == 0
|
||||
? 100
|
||||
: Util.constrainValue((int) ((bufferedPositionMs * 100) / durationMs), 0, 100);
|
||||
: Util.constrainValue(Util.percentInt(bufferedPositionMs, durationMs), 0, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@
|
||||
package androidx.media3.transformer;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Util.percentInt;
|
||||
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
||||
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||
@ -275,7 +276,7 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
|
||||
// The player position can become greater than the duration. This happens if the player is
|
||||
// using a StandaloneMediaClock because the renderers have ended.
|
||||
long positionMs = min(player.getCurrentPosition(), durationMs);
|
||||
progressHolder.progress = (int) (positionMs * 100 / durationMs);
|
||||
progressHolder.progress = percentInt(positionMs, durationMs);
|
||||
}
|
||||
return progressState;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package androidx.media3.transformer;
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static androidx.media3.common.util.Util.percentInt;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.SampleConsumer.INPUT_RESULT_END_OF_STREAM;
|
||||
import static androidx.media3.transformer.SampleConsumer.INPUT_RESULT_TRY_AGAIN_LATER;
|
||||
@ -26,7 +27,6 @@ import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE;
|
||||
import static androidx.media3.transformer.TransformerUtil.getValidColor;
|
||||
import static java.lang.Math.min;
|
||||
import static java.lang.Math.round;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
@ -141,7 +141,7 @@ public final class RawAssetLoader implements AssetLoader {
|
||||
if (lastTimestampUs == Long.MAX_VALUE) {
|
||||
lastTimestampUs = 0;
|
||||
}
|
||||
progressHolder.progress = round((lastTimestampUs / (float) editedMediaItem.durationUs) * 100);
|
||||
progressHolder.progress = percentInt(lastTimestampUs, editedMediaItem.durationUs);
|
||||
}
|
||||
return progressState;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||
import static androidx.media3.common.util.Util.percentInt;
|
||||
import static androidx.media3.effect.DebugTraceUtil.COMPONENT_ASSET_LOADER;
|
||||
import static androidx.media3.effect.DebugTraceUtil.EVENT_INPUT_FORMAT;
|
||||
import static androidx.media3.effect.DebugTraceUtil.EVENT_OUTPUT_FORMAT;
|
||||
@ -178,7 +179,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
return progressState;
|
||||
}
|
||||
|
||||
int progress = currentMediaItemIndex * 100 / mediaItemCount;
|
||||
int progress = percentInt(currentMediaItemIndex, mediaItemCount);
|
||||
if (progressState == PROGRESS_STATE_AVAILABLE) {
|
||||
progress += progressHolder.progress / mediaItemCount;
|
||||
}
|
||||
|
@ -17,13 +17,13 @@ package androidx.media3.transformer;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Util.percentInt;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.SampleConsumer.INPUT_RESULT_END_OF_STREAM;
|
||||
import static androidx.media3.transformer.SampleConsumer.INPUT_RESULT_TRY_AGAIN_LATER;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
|
||||
import static androidx.media3.transformer.TransformerUtil.getValidColor;
|
||||
import static java.lang.Math.round;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
@ -106,7 +106,7 @@ public final class TextureAssetLoader implements AssetLoader {
|
||||
public @Transformer.ProgressState int getProgress(ProgressHolder progressHolder) {
|
||||
if (progressState == PROGRESS_STATE_AVAILABLE) {
|
||||
progressHolder.progress =
|
||||
round((lastQueuedPresentationTimeUs / (float) editedMediaItem.durationUs) * 100);
|
||||
percentInt(lastQueuedPresentationTimeUs, editedMediaItem.durationUs);
|
||||
}
|
||||
return progressState;
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ package androidx.media3.transformer;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.lang.Math.min;
|
||||
import static java.lang.Math.round;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
@ -118,8 +116,7 @@ public class RawAssetLoaderTest {
|
||||
|
||||
assertThat(queuedAudioData).isTrue();
|
||||
assertThat(progressState).isEqualTo(PROGRESS_STATE_AVAILABLE);
|
||||
assertThat(progressHolder.progress)
|
||||
.isEqualTo(round(audioSamplePresentationTimeUs * 100 / (float) audioDurationUs));
|
||||
assertThat(progressHolder.progress).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -168,8 +165,7 @@ public class RawAssetLoaderTest {
|
||||
|
||||
assertThat(queuedInputTexture).isTrue();
|
||||
assertThat(progressState).isEqualTo(PROGRESS_STATE_AVAILABLE);
|
||||
assertThat(progressHolder.progress)
|
||||
.isEqualTo(round(videoSamplePresentationTimeUs * 100 / (float) videoDurationUs));
|
||||
assertThat(progressHolder.progress).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -199,12 +195,7 @@ public class RawAssetLoaderTest {
|
||||
assertThat(queuedAudioData).isTrue();
|
||||
assertThat(queuedInputTexture).isTrue();
|
||||
assertThat(progressState).isEqualTo(PROGRESS_STATE_AVAILABLE);
|
||||
assertThat(progressHolder.progress)
|
||||
.isEqualTo(
|
||||
round(
|
||||
min(audioSamplePresentationTimeUs, videoSamplePresentationTimeUs)
|
||||
* 100
|
||||
/ (float) mediaDurationUs));
|
||||
assertThat(progressHolder.progress).isEqualTo(10);
|
||||
}
|
||||
|
||||
private static EditedMediaItem getEditedMediaItem(long mediaDurationUs) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user