From ebbcec9a2034240a6a8647393dbe4650fd37f368 Mon Sep 17 00:00:00 2001 From: tofunmi Date: Fri, 28 Jul 2023 09:29:37 +0100 Subject: [PATCH] Add imageDurationMs to MediaItem PiperOrigin-RevId: 551776350 --- .../androidx/media3/common/MediaItem.java | 43 ++++++++++++++++--- .../androidx/media3/common/MediaItemTest.java | 16 +++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/MediaItem.java b/libraries/common/src/main/java/androidx/media3/common/MediaItem.java index cb0174f778..926dde3a42 100644 --- a/libraries/common/src/main/java/androidx/media3/common/MediaItem.java +++ b/libraries/common/src/main/java/androidx/media3/common/MediaItem.java @@ -15,6 +15,7 @@ */ package androidx.media3.common; +import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; @@ -77,6 +78,7 @@ public final class MediaItem implements Bundleable { private ImmutableList subtitleConfigurations; @Nullable private AdsConfiguration adsConfiguration; @Nullable private Object tag; + private long imageDurationMs; @Nullable private MediaMetadata mediaMetadata; // TODO: Change this to LiveConfiguration once all the deprecated individual setters // are removed. @@ -92,6 +94,7 @@ public final class MediaItem implements Bundleable { subtitleConfigurations = ImmutableList.of(); liveConfiguration = new LiveConfiguration.Builder(); requestMetadata = RequestMetadata.EMPTY; + imageDurationMs = C.TIME_UNSET; } private Builder(MediaItem mediaItem) { @@ -114,6 +117,7 @@ public final class MediaItem implements Bundleable { ? localConfiguration.drmConfiguration.buildUpon() : new DrmConfiguration.Builder(); adsConfiguration = localConfiguration.adsConfiguration; + imageDurationMs = localConfiguration.imageDurationMs; } } @@ -555,6 +559,22 @@ public final class MediaItem implements Bundleable { return this; } + /** + * Sets the image duration in video output, in milliseconds. + * + *

Must be set if {@linkplain #setUri the uri} is set and resolves to an image. Ignored + * otherwise. + * + *

Default value is {@link C#TIME_UNSET}. + */ + @CanIgnoreReturnValue + @UnstableApi + public Builder setImageDurationMs(long imageDurationMs) { + checkArgument(imageDurationMs > 0 || imageDurationMs == C.TIME_UNSET); + this.imageDurationMs = imageDurationMs; + return this; + } + /** Sets the media metadata. */ @CanIgnoreReturnValue public Builder setMediaMetadata(MediaMetadata mediaMetadata) { @@ -585,7 +605,8 @@ public final class MediaItem implements Bundleable { streamKeys, customCacheKey, subtitleConfigurations, - tag); + tag, + imageDurationMs); } return new MediaItem( mediaId != null ? mediaId : DEFAULT_MEDIA_ID, @@ -599,7 +620,6 @@ public final class MediaItem implements Bundleable { /** DRM configuration for a media item. */ public static final class DrmConfiguration implements Bundleable { - /** Builder for {@link DrmConfiguration}. */ public static final class Builder { @@ -1128,6 +1148,9 @@ public final class MediaItem implements Bundleable { */ @Nullable public final Object tag; + /** Duration for image assets in milliseconds. */ + @UnstableApi public final long imageDurationMs; + @SuppressWarnings("deprecation") // Setting deprecated subtitles field. private LocalConfiguration( Uri uri, @@ -1137,7 +1160,8 @@ public final class MediaItem implements Bundleable { List streamKeys, @Nullable String customCacheKey, ImmutableList subtitleConfigurations, - @Nullable Object tag) { + @Nullable Object tag, + long imageDurationMs) { this.uri = uri; this.mimeType = mimeType; this.drmConfiguration = drmConfiguration; @@ -1151,6 +1175,7 @@ public final class MediaItem implements Bundleable { } this.subtitles = subtitles.build(); this.tag = tag; + this.imageDurationMs = imageDurationMs; } @Override @@ -1170,7 +1195,8 @@ public final class MediaItem implements Bundleable { && streamKeys.equals(other.streamKeys) && Util.areEqual(customCacheKey, other.customCacheKey) && subtitleConfigurations.equals(other.subtitleConfigurations) - && Util.areEqual(tag, other.tag); + && Util.areEqual(tag, other.tag) + && Util.areEqual(imageDurationMs, other.imageDurationMs); } @Override @@ -1183,6 +1209,7 @@ public final class MediaItem implements Bundleable { result = 31 * result + (customCacheKey == null ? 0 : customCacheKey.hashCode()); result = 31 * result + subtitleConfigurations.hashCode(); result = 31 * result + (tag == null ? 0 : tag.hashCode()); + result = (int) (31L * result + imageDurationMs); return result; } @@ -1195,6 +1222,7 @@ public final class MediaItem implements Bundleable { private static final String FIELD_STREAM_KEYS = Util.intToStringMaxRadix(4); private static final String FIELD_CUSTOM_CACHE_KEY = Util.intToStringMaxRadix(5); private static final String FIELD_SUBTITLE_CONFIGURATION = Util.intToStringMaxRadix(6); + private static final String FIELD_IMAGE_DURATION_MS = Util.intToStringMaxRadix(7); /** * {@inheritDoc} @@ -1227,6 +1255,9 @@ public final class MediaItem implements Bundleable { bundle.putParcelableArrayList( FIELD_SUBTITLE_CONFIGURATION, BundleableUtil.toBundleArrayList(subtitleConfigurations)); } + if (imageDurationMs != C.TIME_UNSET) { + bundle.putLong(FIELD_IMAGE_DURATION_MS, imageDurationMs); + } return bundle; } @@ -1253,6 +1284,7 @@ public final class MediaItem implements Bundleable { subtitleBundles == null ? ImmutableList.of() : BundleableUtil.fromBundleList(SubtitleConfiguration.CREATOR, subtitleBundles); + long imageDurationMs = bundle.getLong(FIELD_IMAGE_DURATION_MS, C.TIME_UNSET); return new LocalConfiguration( checkNotNull(bundle.getParcelable(FIELD_URI)), @@ -1262,7 +1294,8 @@ public final class MediaItem implements Bundleable { streamKeys, bundle.getString(FIELD_CUSTOM_CACHE_KEY), subtitleConfiguration, - /* tag= */ null); + /* tag= */ null, + imageDurationMs); } } diff --git a/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java b/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java index 99fe569c98..d7e38a0436 100644 --- a/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java @@ -390,6 +390,22 @@ public class MediaItemTest { assertThat(mediaItem.localConfiguration.tag).isEqualTo(tag); } + @Test + public void builderSetImageDurationMs_isTimeUnsetTByDefault() { + MediaItem mediaItem = new MediaItem.Builder().setUri(URI_STRING).build(); + + assertThat(mediaItem.localConfiguration.imageDurationMs).isEqualTo(C.TIME_UNSET); + } + + @Test + public void builderSetImageDurationMs_setsImageDurationMs() { + long duration = 1; + MediaItem mediaItem = + new MediaItem.Builder().setUri(URI_STRING).setImageDurationMs(duration).build(); + + assertThat(mediaItem.localConfiguration.imageDurationMs).isEqualTo(duration); + } + @Test @SuppressWarnings("deprecation") // Testing deprecated field public void builderSetClippingConfiguration() {